springmvc知识点记录-爱代码爱编程
SpringMVC知识点记录
1. SpringMVC简介
2. 入门案例
文件结构
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>spring_mvc_helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式为war-->
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--
配置SpringMVC的前端控制器,对浏览器发送的请求进行处理
SpringMVC的配置文件的默认位置和名称:
位置:WEB-INF下
名称:<servlet-name>-servlet.xml,当前配置下的配置文件名为SpringMVC-servlet.xml
-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--设置SpringMVC配置文件的位置和名称-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMVC.xml</param-value>
</init-param>
<!--将DispatcherServlet的初始化时间提前到了服务器启动时-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!--
url-pattern:
/:匹配浏览器向服务器发送的所有请求,不包括.jsp
/*:匹配浏览器向服务器发送的所有请求,包括.jsp
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
SpringMVC配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描控制层组件-->
<context:component-scan base-package="com.atguigu.controller"/>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!--/WEB-INF/templates/index.html-->
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
</beans>
请求控制器类
package com.atguigu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
//@RequestMapping注解:处理请求和控制器方法之间的映射关系
//@RequestMapping注解的value属性可以通过请求地址匹配请求,/表示的当前工程的上下文路径
@RequestMapping("/")
public String protal(){
//将逻辑视图返回
return "index";
}
@RequestMapping("/hello")
public String hello(){
return "success";
}
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>xixi</h3>
<a th:href="@{/hello}">测试SpringMVC</a>
</body>
</html>
sucess.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>成功</h1>
</body>
</html>
3. @RequestMapping注解
3.1 @RequestMapping注解的功能
@RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。
3.2 @RequestMapping注解的位置
@RequestMapping注解标识的位置:
1、标识一个类:设置映射请求的请求路径的初始信息
2、标识一个方法:设置映射请求的请求路径的具体信息
/**
* @RequestMapping注解标识的位置:
* 1、标识一个类:设置映射请求的请求路径的初始信息
* 2、标识一个方法:设置映射请求的请求路径的具体信息
*/
@Controller
@RequestMapping("/test")
public class TestRequestMappingController {
//此时控制器方法所匹配的请求的请求路径为/test/hello
@RequestMapping("/hello")
public String helloworld(){
return "success";
}
}
3.3 @RequestMapping注解的value属性
@RequestMapping注解values属性:
作用: 通过请求的请求路径匹配请求;
value属性是数组类型,即若当前浏览器所发送请求的请求路径匹配value属性中的任何一个值,则当前请求就会被注解所标识的方法进行处理。
/**
* @RequestMapping注解values属性:
* 作用:通过请求的请求路径匹配请求;
* value属性是数组类型,即若当前浏览器所发送请求的请求路径匹配value属性中的任何一个值,则当前请求就会被注解所标识的方法进行处理。
*/
@Controller
@RequestMapping("/test")
public class TestRequestMappingController {
//此时控制器方法所匹配的请求的请求路径为/test/hello或者/test/abc
@RequestMapping({"/hello","/abc"})
public String helloworld(){
return "success";
}
}
3.4 @RequestMapping注解的method属性
@RequestMapping注解的method属性
作用: 通过请求的请求方式匹配请求;
method属性时RequestMethod类型的数组,即若当前浏览器所发送请求的请求方式匹配method属性中的任何一种请求方式,则前请求就会被注解所标识的方法进行处理。
常见的异常报错
若浏览器所发送的请求的请求路径和@RequestMapping注解value属性匹配,但是请求方式不匹配,则此时页面报错405
注意:
除了表单提交、Ajax请求等是post请求之外,基本都是get请求
/**
* @RequestMapping注解的method属性
* 作用:通过请求的请求方式匹配请求;
* method属性时RequestMethod类型的数组,即若当前浏览器所发送请求的请求方式匹配method属性中的任何一种请求方式,则前请求就会被注解所标识的方法进行处理。
* 若浏览器所发送的请求的请求路径和@RequestMapping注解value属性匹配,但是请求方式不匹配,则此时页面报错405
*/
@Controller
@RequestMapping("/test")
public class TestRequestMappingController {
//此时控制器方法所匹配的请求的请求路径为/test/hello或者/test/abc
@RequestMapping(value = {"/hello","/abc"},method = RequestMethod.POST)
public String helloworld(){
return "success";
}
}
在@RequestMapping的基础上,结合请求方式的一些派生注解:
@GetMapping、@PostMapping、@DeleteMapping、@PutMapping
3.5 @RequestMapping注解的params属性(了解)
/**
* @RequestMapping注解的params属性:
* 作用:通过请求的请求参数匹配请求,即浏览器发送的请求的请求参数必须满足params属性的设置;
*
* params可以使用四种表达式:
* "param":当前请求的请求参数中必须携带param参数;
* "!param":当前请求的请求参数中不能携带param参数;
* "param=value":当前请求的请求参数中必须携带param参数,且值为value;
* "param!=value":当前请求的请求参数中可以不携带param参数,如果携带了param参数,必须不能等于value。(简言之,不能接待value的param参数);
*
* 参数不符合时,报错:400-Parameter conditions "username" not met for actual request parameters:
*/
@Controller
@RequestMapping("/test")
public class TestRequestMappingController {
//此时控制器方法所匹配的请求的请求路径为/test/hello或者/test/abc
@RequestMapping(value = {"/hello", "/abc"}, method = {RequestMethod.POST, RequestMethod.GET},params ={"username","!password","age=20","sex=女"}
)
public String helloworld() {
return "success";
}
}
3.6 @RequestMapping注解的headers属性(了解)
/**
* @RequestMapping注解的headers属性:
* "header":要求请求映射所匹配的请求必须携带header请求头信息
* "!header":要求请求映射所匹配的请求必须不能携带header请求头信息
* "header=value":要求请求映射所匹配的请求必须携带header请求头信息且header=value
* "header!=value":要求请求映射所匹配的请求必须携带header请求头信息且header!=value
*
* headers = {"referer"} 请求头中必须含有referer属性,代表着必须有来源页面,代表着不能靠手动输入地址来访问二级以下的页面;
*
* 注意:若浏览器所发送的请求的请求路径和@RequestMapping注解value属性匹配,但是请求头不匹配,则报错404
*/
@Controller
@RequestMapping("/test")
public class TestRequestMappingController {
//此时控制器方法所匹配的请求的请求路径为/test/hello或者/test/abc
@RequestMapping(
value = {"/hello", "/abc"},
method = {RequestMethod.POST, RequestMethod.GET},
headers = {"referer"}
)
public String helloworld() {
return "success";
}
}
3.7 SpringMVC支持ant风格的路径
?:表示任意的单个字符
*
:表示任意的0个或多个字符
**
:表示任意层数的任意目录
注意:在使用时,只能使用//xxx的方式
// a?a :a和a的中间可以表示任意一个字符,例如/test/aba/ant。但是注意有些特殊字符(?)除外。
//@RequestMapping("/a?a/ant")
// a*a :a和a的中间可以表示任意一个字符,例如/test/abba/ant。但是注意有些特殊字符(?和/)除外。
//@RequestMapping("/a*a/ant")
// 代表多层目录 例如:/test/abba/abba/ant
@RequestMapping("/**/ant")
public String testAnt(){
return "success";
}
3.8 SpringMVC支持路径中的占位符(重点)
/**
* SpringMVC使用路径中的占位符
* 传统方式:/deleteUser?id=1
* rest方式:/user/delete/1
* 需要在@RequestMapping注解的value属性中所设置的路径中,使用{xxx}的方式表示路径中的数据,
* 再通过@PathVariable注解,将占位符所标识的值和控制器方法的形参进行绑定
*/
@RequestMapping("/rest/{id}/{username}")
public String testRest(@PathVariable("id") Integer id,@PathVariable("username") String username){
System.out.println("id="+id+";username="+username);//最终输出结果:id=1;username=admin
return "success";
}
4. SpringMVC获取请求参数
4.1 通过ServletAPI获取请求参数
/**
* 1、通过ServletAPI获取请求参数
* 只需要在控制器方法的形参位置设置HttpServletRequest类型的形参,就可以在控制器方法中使用request对象获取请求参数。
* @param request
* @return
*/
@RequestMapping("/param/servletAPI")
public String getParamByServletAPI(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username="+username+";password="+password);//输出结果:username=admin;password=123
return "success";
}
4.2 通过控制器方法的形参获取请求参数
/**
* 2、通过控制器方法的形参获取
* 只需要在控制器方法的形参位置设置一个形参,形参的名字要和请求参数的名字一致即可。
* @param username
* @param password
* @return
*/
//通过控制器方法的形参获取请求参数
@RequestMapping("/param1")
public String getParam1(String username,String password){
System.out.println("username="+username+";password="+password);//输出结果:username=admin;password=123
return "success";
}
4.3 @RequestParam注解
/**
* 3、@RequestParam注解
* 通过控制器方法的形参获取请求参数,并且使用@RequestParam注解解决形参和前端请求参数名字不一致的情况
* @RequestParam注解:将请求参数和控制器方法的形参进行绑定;
* 三个属性:
* value = "userName" :设置和形参绑定的请求参数的名字;
* required = false :设置是否必须传输value所对应的请求参数,默认值为true;
* 注意:若设置了required = true,而没有传输则会报错 400;
* defaultValue = "User1" :设置当没有传输value所对应的请求参数时,为形参设置默认值,前提是需要设置required = false;
*
*/
@RequestMapping("/param2")
public String getParam2(@RequestParam(value = "userName") String username, @RequestParam("passWord") String password){
System.out.println("username="+username+";password="+password);//输出结果:username=admin;password=123
return "success";
}
4.4 @RequestHeader注解 和 @CookieValue注解
@RequestHeader是将请求头信息和控制器方法的形参创建映射关系
@RequestHeader注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
@CookieValue是将cookie数据和控制器方法的形参创建映射关系
@CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
/**
* 3、@RequestParam注解
* 通过控制器方法的形参获取请求参数,并且使用@RequestParam注解解决形参和前端请求参数名字不一致的情况
* @RequestParam注解:将请求参数和控制器方法的形参进行绑定;
* 三个属性:
* value = "userName" :设置和形参绑定的请求参数的名字;
* required = false :设置是否必须传输value所对应的请求参数,默认值为true;
* 注意:若设置了required = true,而没有传输则会报错 400;
* defaultValue = "User1" :设置当没有传输value所对应的请求参数时,为形参设置默认值,前提是需要设置required = false;
* 4、@RequestHeader注解:将请求头信息和控制器方法的形参绑定
* 5、@CookieValue注解:将cookie数据和控制器方法的形参绑定
*/
@RequestMapping("/param2")
public String getParam2(
@RequestParam(value = "userName") String username,
@RequestParam("passWord") String password,
@RequestHeader("referer") String referer,
@CookieValue("JSESSIONID") String jsessionId
){
System.out.println("username="+username+";password="+password);//输出结果:username=admin;password=123
System.out.println("referer="+referer);//输出结果:referer=http://localhost:8080/spring_mvc_demo_war_exploded/
System.out.println("cookie="+jsessionId);//输出结果:cookie=61A430AE2B0EC2959F2C0C0B3825A8B5
return "success";
}
4.5 通过POJO获取请求参数
/**
* 通过控制器方法的实体类型的形参获取请求参数:
* 需要在控制器方法的形参位置设置实体类类型的形参,要保证实体类中的属性的属性名和请求参数的名字一致,可以通过实体类类型的形参获取请求参数。
* @param user
* @return
*/
@RequestMapping("param/pojo")
public String getParamByPojo(User user){
System.out.println(user); //输出结果:User{id=null, username='admin', password='123'}
return "success";
}
4.6 解决获取请求参数的乱码问题
tomcat8以后get请求不需要解决乱码问题,post请求需要自己来解决;
web.xml中加入配置(SpringMVC中处理编码的过滤器一定要配置到其他过滤器之前,否则无效)
<!--配置Spring的编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5. 域对象共享数据
5.1 使用ServletAPI想request域对象共享数据(不常用)
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
request.setAttribute("testScope", "hello,servletAPI");
return "success";
}
5.2 使用ModelAndView向request域对象共享数据
/**
* 向域对象共享数据:
* 1、通过ModelAndView向请求域共享数据
* 使用ModelAndView时,可以使用其Model功能向请求域共享数据
* 使用View功能设置逻辑视图,但是控制器方法一定要将ModelAndView作为方法的返回值
* @return
*/
@RequestMapping("/test/mav")
public ModelAndView testMAV(){
/**
* ModelAndView包含Model和View的功能:
* Model:向请求域中共享数据;
* View:设置逻辑视图实现页面跳转;
*/
ModelAndView mav = new ModelAndView();
//向请求域中共享数据
mav.addObject("testRequestScope", "hello,ModelAndView");
//设置逻辑视图
mav.setViewName("success");
return mav;
}
success.html
<p th:text="${testRequestScope}"></p>
运行结果
5.3 使用Model向request域对象共享数据
/**
* 使用Model向请求域中共享数据
* @param model
* @return
*/
@RequestMapping("/test/model")
public String testModel(Model model){
model.addAttribute("testRequestScope","hello,Model");
return "success";
}
运行结果
5.4 使用ModelMap向request域对象共享数据
/**
* 使用ModelMap向请求域中共享数据
* @param modelMap
* @return
*/
@RequestMapping("/test/modelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testRequestScope","hello,ModelMap");
return "success";
}
运行结果
5.5 使用map向request域对象共享数据
/**
* 使用Map向请求域中共享数据
* @param map
* @return
*/
@RequestMapping("/test/map")
public String testMap(Map<String,Object> map){
map.put("testRequestScope","hello,Map");
return "success";
}
运行结果
5.6 Model、ModelMap、Map的关系
Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的
public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object> {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class BindingAwareModelMap extends ExtendedModelMap {}
5.7 向session域共享数据
/**
* 向session域共享数据
* @param session
* @return
*/
@RequestMapping("/test/session")
public String testSession(HttpSession session){
session.setAttribute("testSessionScope","hello,session");
return "success";
}
success.html
<p th:text="${session.testSessionScope}"></p><br>
运行结果
5.8 向application域共享数据
/**
* 向application域共享数据
* @param session
* @return
*/
@RequestMapping("/test/application")
public String testApplication(HttpSession session){
ServletContext servletContext = session.getServletContext();
servletContext.setAttribute("testApplicationScope","hello,application");
return "success";
}
success.html
<p th:text="${application.testApplicationScope}"></p><br>
运行结果
6.SpringMVC的视图
6.1 ThymeleafView
当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置
的视图解析器解析,视图名称拼接视图前缀和视图
后缀所得到的最终路径,会通过转发的方式实现跳转
@RequestMapping("/test/view/thymeleaf")
public String testThymeleafView(){
return "success";
}
6.2 转发视图 InternalResourceView
/**
* 转发视图:InternalResourceView
* @return
*/
@RequestMapping("/test/view/forward")
public String testInternalResourceView(){
return "forward:/test/model";
}
运行结果
6.3 重定向视图 RedirectView
/**
* 重定向视图:RedirectView
* @return
*/
@RequestMapping("/test/view/redirect")
public String testRedirectView(){
return "redirect:/test/model";
}
运行结果
6.4 视图控制器 view-controller
当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示
SpringMVC.xml
<!--开启mvc的注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--
视图控制器:为当前的请求直接设置视图名称实现页面跳转
若设置视图控制器,则只有视图控制器所设置的请求会被处理,其他的请求将全部404,
此时必须再配置一个标签来开启mvc的注解驱动(<mvc:annotation-driven></mvc:annotation-driven>)
-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
7. RESTful
7.1 RESTful简介
REST:Representational State Transfer,表现层资源状态转移。
7.2 RESTful的实现
GET 用来获取资源;
POST 用来新建资源;
PUT 用来更新资源;
DELETE用来删除资源;
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数。
而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。
操作 | 传统方式 | REST风格 |
---|---|---|
查询操作 | getUserById?id=1 | user/1 (get请求方式) |
保存操作 | saveUser | user (post请求方式) |
删除操作 | deleteUser?id=1 | user/1 (delete请求方式) |
更新操作 | updateUser | user (put请求方式) |
查询操作
/**
* 查询所有用户信息
* @return
*/
@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getAllUser(){
System.out.println("查询所有用户信息 --> /user --> get");
return "success";
}
/**
* 根据id查询用户信息
* @param id
* @return
*/
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public String getUserById(@PathVariable("id") Integer id){
System.out.println("根据id查询用户信息 --> /user/"+id+" --> get");
return "success";
}