SpringMVC——前后端传参常用注解总结
文章目录
- SpringMVC——前后端传参常用注解总结
- 一、准备一个获取登录信息的案例
- 1. 开发环境准备
- 2. 新建Maven模块
- 3. 在main下新建一个webapp目录
- 4. 添加web.xml文件
- 5.配置web.xml文件
- 6. 在resources目录下创建springmvc.xml文件
- 7. 在java目录下创建package(实体类、控制层)
- 8. 在WEB-INF目录下新建文件夹thymeleaf
- 9. 此时配置tomcat服务器,测试程序运行是否正常
- 二、具体注解学习
- 1. @RequestMapping
- 2. @GetMapping
- 3. @PostMapping
- 4. @RequestParam
- 5. @RequestBody
- 6. @PathVariable
- 7. @RestController
- 7. @RestController
一、准备一个获取登录信息的案例
1. 开发环境准备
- IDEA
- Tomcat10
- Maven
- JDK17
2. 新建Maven模块
- Maven记得配置为自己的本地Maven:Settings->Build->Build Tools->Maven
-
pom.xml文件中添加依赖,添加完记得刷新
<!--打包方式:war--> <packaging>war</packaging> <!--依赖--> <dependencies> <!--springmvc依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.1.4</version> </dependency> <!--servlet依赖--> <dependency> <!--tomcat10版本使用jakarta--> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <!--指定依赖的范围,provideed指该依赖会被第三方容器提供,不会打包的war包中--> <scope>provided</scope> </dependency> <!--logback依赖--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.5.3</version> </dependency> <!--thymeleaf和spring6整合依赖--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring6</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!--处理json格式--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.2</version> </dependency> </dependencies>
3. 在main下新建一个webapp目录
-
注意,在pom.xml文件依赖添加完后进行该步,会创建一个标准的webapp目录
4. 添加web.xml文件
-
点击Apply和Ok后出现该目录
5.配置web.xml文件
-
DispatcherServlet是一个前端控制器。在Spring MVC中,它扮演了一个至关重要的角色。当用户在浏览器发出一个HTTP请求时,该请求会先到达DispatcherServlet。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <!--配置前端控制器(DispatcherServlet)--> <servlet> <servlet-name>springmvc</servlet-name> <!--DispatcherServlet是SpringMVC中处理HTTP请求的核心组件--> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!--指定了SpringMVC配置文件的路径(类的根路径)和名称(springmvc.xml)--> <param-value>classpath:springmvc.xml</param-value> </init-param> <!--指定该控制器在服务器启动时的启动优先级--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!--例如/login这样的请求路径都会经过该控制器--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
6. 在resources目录下创建springmvc.xml文件
-
编写springmvc.xml文件
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 开启注解驱动,改配置用于接收前端发来的JSON数据 --> <mvc:annotation-driven> <mvc:message-converters> <!-- 配置 JSON 消息转换器 --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"> <!-- 可以配置更多 Jackson ObjectMapper 的属性 --> <property name="serializationInclusion" value="NON_NULL"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!--配置组件扫描--> <context:component-scan base-package="pers.weiney.springmvc.controller"/> <!--配置视图解析器--> <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> <!--作用于视图渲染的过程中,可以设置视图渲染后输出时采用的编码字符集--> <property name="characterEncoding" value="UTF-8"/> <!--如果配置多个视图解析器,它来决定优先使用哪个视图解析器,它的值越小优先级越高--> <property name="order" value="1"/> <!--当 ThymeleafViewResolver 渲染模板时,会使用该模板引擎来解析、编译和渲染模板--> <property name="templateEngine"> <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> <!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息,加载模板并对其进行解析--> <property name="templateResolver"> <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/thymeleaf/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean> </beans>
7. 在java目录下创建package(实体类、控制层)
-
pojo包下新建User.java类
package pers.weiney.springmvc.pojo; /** * @author Weiney * @ToDo * @create 2024-07-31 15:47 */ public class User { private String username; // 用户名 private String password; // 用户密码 public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
controller包下新建IndexController.java
package pers.weiney.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author Weiney * @ToDo * @create 2024-07-31 16:18 */ // Controller注解用于标识该控制器类,将其纳入Spring框架进行管理,控制器层负责处理前端HTTP请求,协调业务逻辑的处理 @Controller public class IndexController { // 浏览器中访问http://localhost:9999/springmvc/,前端控制器会根据最后一个/,进行请求映射到该方法 @RequestMapping("/") public String Index(){ // 返回逻辑视图,视图解析器会将其转为物理视图,路径拼接成/WEB-INF/thymeleaf/index.html return "index"; } }
8. 在WEB-INF目录下新建文件夹thymeleaf
-
在该thymeleaf目录下新建html文件index.html
<!DOCTYPE html> <html lang="zh-cn" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>用户登录</title> </head> <body> <h1>用户登录</h1> <!--点击登录后会发出请求:http://localhost:9999/springmvc/user/login,且会在控制器中对应一个方法--> <form th:action="@{/user/login}" method="post"> 账号:<input type="text" name="username"><br> 密码:<input type="password" name="password"> <input type="submit" value="点击登录"> </form> </body> </html>
-
此时回到IndexController中新增一个方法,路径映射到该方法上
@RequestMapping("/user/login") public String login(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; }
-
并编写一个用于登录成功返回的页面ok.html
-
内容如下:
<!DOCTYPE html> <html lang="zh-cn" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录成功</title> </head> <body> <h1>登录成功</h1> </body> </html>
9. 此时配置tomcat服务器,测试程序运行是否正常
-
启动该服务器,浏览器中访问:http://localhost:8888/springmvc/
二、具体注解学习
前言:注解式开发可以提高代码的可读性和可维护性,且开发过程中简化了大量配置文件和复杂的代码,框架的作用也体现在此,复杂的事情交给框架来做,我们直接使用框架封装好的类,提高开发效率。
1. @RequestMapping
-
作用:将前端发送的请求映射到相应的处理方法上,从而实现对请求的处理和响应。
-
RequestMapping注解只能出现在类上或者方法上。
-
@RequestMapping("/user/login") public String login(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; }
-
@RequestMapping("/user/register") public String register(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; }
-
@Controller @RequestMapping("/user") public class IndexController { @RequestMapping("/login") public String login(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; } @RequestMapping("/register") public String register(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; } }
-
-
value属性:字符串数组,别名path
-
多个不同的请求路径映射到同一个控制器的同一个方法上:
@RequestMapping(value={"/page1", "/page2", "page3"})
-
当只有一个请求路径"/page1"时:value={}可以不写,简写为"/page1"
@RequestMapping("/page1")
-
value里的路径是支持模糊匹配的,这种模糊匹配称之为Ant风格
-
?:代表任意一个字符,某些特殊字符不可以
@RequestMapping("/a?c/login"),
-
*:代表0到N个任意字符
@RequestMapping("/a*c/login")
-
**:代表0到N个任意字符,并且路径中可以出现路径分隔符 /
@RequestMapping("/page1/**")
-
-
-
method属性:枚举类型数组
public enum RequestMethod { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; // ... }
-
如何使用:
@RequestMapping("/user/login", method = RequestMethod.POST) // 同样method = RequestMethod.POST有简写形式,下文会有介绍 public String login(){ // 获取参数,业务处理 // 返回逻辑视图 return "ok"; }
-
作用:限制客户端的请求方式。如浏览器发送get请求,数据会显示在URL上,若是登录密码则有泄漏的可能性,因此此时需要发送post请求,请求的参数在请求体中,相对更安全。因此后端可以强制接收POST方式的请求,即在@RequestMapping注解中规定所需要的请求方式。
-
若请求方式不一致,会报HTTP状态码:405错误,方法不允许。
-
-
params属性:和value属性类似,也是一个字符串数组,但params属性,要求浏览器发送的请求参数必须和params数组中的参数完全一致才可以映射到相应方法上。
-
如何使用:4种表示方法
// 1. 请求路径中必须包含username参数和password参数,才能映射到当前方法 @RequestMapping(value="/login", params={"username", "password"}) // 2. 请求路径中不能包含username参数,但需要有password参数,才能映射到当前方法 @RequestMapping(value="/login", params={"!username", "password"}) // 3. 请求路径中的username参数值必须为admin,且有password参数,才能映射到当前方法 @RequestMapping(value="/login", params={"username=admin", "password"}) // 4. 请求路径中的username参数值不是admin,且有password参数,才能映射到当前方法 @RequestMapping(value="/login", params={"username!=admin", "password"})
-
如果前端提交的参数,和后端要求的请求参数不一致,会出现HTTP状态码:400错误,请求参数格式不正确导致的。
-
-
headers属性:使用形式和params属性类似
// 如请求头中必须包含Referer和Host // 浏览器中F12可以查看 // Referer: http://localhost:8080/springmvc/ // 键是Referer,值是http://localhost:8080/springmvc/ // Host: localhost:8080,键是Host,值是localhost:8080 @RequestMapping(value="/login", headers={"Referer", "Host"})
2. @GetMapping
-
等同于:
@RequestMapping("/login", method = RequestMethod.GET)
-
使用此注解时,不需要指定method属性,且其他属性使用方法和@RequestMapping一致。
3. @PostMapping
-
等同于:
@RequestMapping("/login", method = RequestMethod.POST)
-
除此外还有@PutMapping、@DeleteMapping等。
4. @RequestParam
-
作用:获取浏览器提交的数据,如username、password等,将
请求参数
与方法上的形参
映射。。 -
SpringMVC底层就是封装了Java的Servlet(Java编写的服务器端程序,可以交互式浏览和生成数据,生成动态Web内容),若用Servlet接口中的方法获取参数,如下:
@PostMapping(value="/login") public String login(HttpServletRequest request){ // 通过当前请求对象request获取提交的数据 String username = ; String password = ; // ... }
-
那么封装了Servlet的SpringMVC框架如何获取浏览器提交的参数呢?
@RequestMapping("/user/login") public String login( ... String username, ... String password){ // 获取参数,业务处理 System.out.println("username: " + username + " \npassword: " + password); // 返回逻辑视图 return "ok"; }
-
看一下该@RequestParam注解的源码
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) // 注解的保留方式 @Documented // java生成说明文档时,声明是否显示该注解 public @interface RequestParam { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; boolean required() default true; String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n"; }
-
value属性(或name属性,互为别名):
- @RequestParam(value=“username”),注:注解中的value的值一定不要写错,最好从前端页面中复制标签的id,否则会报400错误:错误的请求。
-
required属性:
-
默认为
true
,表示方法参数是必需的。如果请求中缺少对应的参数,则会抛出异常。-
可以设置为false表示不是必需的,若请求缺少对应参数,则方法的参数为null。
@RequestMapping("/user/login") public String login( // 此时,若请求信息中不包含username,也不会报错 @RequestParam(value="username", required="false") String username){ // 返回逻辑视图 return "ok"; }
-
-
-
defaultValue属性:
-
用来设置形参的默认值,即当
没有提供对应的请求参数
或者请求参数的值是空字符串""
的时候,方法的形参会采用默认值。@RequestMapping("/user/login") public String login( // 此时,若请求信息中不包含username,则username默认值为admin @RequestParam(value="username", required="false", defaultValue="admin") String username){ // 返回逻辑视图 return "ok"; }
-
@RequestParam 这个注解是可以省略的,如果方法形参的名字和提交数据时的name相同,则 @RequestParam 可以省略。但是在Spring6+版本以上,需要在pom.xml文件中配置一些信息(这里就不作展开了)。
-
-
若是需要获取的参数有很多,用@RequestParam一个一个写就会显得很繁琐,因此有以下方式:
-
将需要获取的参数封装为一个实体类,如本教程案例中的pojo类中的User类。
@RequestMapping("/user/login") public String login(User user){ // 底层原理是Java的反射机制 System.out.println(user); // 返回逻辑视图 return "ok"; }
- 该User中必须含有对应属性的setter()方法,如参数username,则对应setter方法为setUsername()。
-
5. @RequestBody
-
@RequestBody主要用来接收
前端
传递给后端
的json字符串
中的数据
的(请求体中的数据的)。-
前后端数据交互的方式有很多种,如本案例的表单,还有如JavaScript中的ajax方式(可以异步加载,无刷新更新内容)来进行数据交互,此时可以将数据封装为json格式。
-
这里我们采用Postman接口测试工具,来向后端发送一个使用json格式的数据
-
后端代码IndexController.java中
@RequestMapping("/user/add") public String addUser(@RequestBody User user){ System.out.println(user); return "ok"; }
-
Postman中输入如下:
-
-
使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST等方式进行提交。
-
当@RequestBody将数据装配到目标类(User.java)时,会根据json字符串中的key来匹配对应实体类的属性,此时会调用实体类中的setter方法进行赋值。
-
6. @PathVariable
-
先介绍一种设计风格:RESTFul风格,这只是一种风格,不是一种协议,可以使用XML格式定义。
-
RESTFul是面向资源的,每个资源都会有一个唯一的资源标识符(URI),客户端通过HTTP请求访问这些资源,并使用HTTP方法来执行特定的操作。
-
传统方式:
// 发送的请求URL为:http://localhost:8080/springmvc/getUser?id=1 // 后端获取该参数方法 @GetMapping("/getUser") public String getUser(@RequestParam("id") Integer id){ System.out.println("要查询的用户id为:" + id); // 业务逻辑代码 return "ok"; }
-
使用RESTFul风格:
// 发送的请求URL为:http://localhost:8080/springmvc/getUser/1 // 此时我们可以看到两种风格的区别,前者数据在参数部分,后者在路径部分 @GetMapping("/getUser/{id}") public String getUserByPath(@PathVariable("id") Integer id){ System.out.println("要查询的用户id为:" + id); // 业务逻辑代码 return "ok"; }
-
此时我们可以看到@RequestParam与@PathVariable这俩个注解的区别了:
- 当我们需要URL中的参数通过路径传参时,使用@PathVariable注解,当使用参数传参时,使用@RequestParam传参。
- 什么时候路径传参、参数传参呢?建议当URL指向某一具体资源时,会使用路径传参,如访问某个人的博客,https://blogs/{blogId},而筛选某篇文章时,会用https://blogs?state=publish。总的来说,指向具体:路径,筛选过滤资源:参数传参。
-
@PathVariable中的参数也与@RequestParam类似,源码如下:
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PathVariable { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; boolean required() default true; }
-
7. @RestController
-
@RestController是
@Controller
和@ResponseBody
的组合(@ResponseBody会将java对象直接返回写入到响应体中,一般为JSON数据)。 -
使用
@RestController
注解的类会自动被Spring MVC识别为控制器,并将其方法的返回值作为HTTP响应的正文。 -
将对如下示例进行解析:
@RestController @RequestMapping("/user") public class UserController { @GetMapping("/list") public List<User> listUsers() { // 返回用户列表 // 返回值会被自动序列化为JSON格式 } }
- @RestController这个注解表明
UserController
类是一个控制器,并且它的所有方法的返回值都将被序列化为JSON(或其它配置的格式),直接作为HTTP响应的正文返回。
- @RestController这个注解表明
-
什么时候使用@RestController?
-
在Web应用程序中,前端页面可能需要请求用户列表以展示给用户。
-
响应的数据是一个java对象,内容较多时,SpringMVC会自动将返回的对象序列化为JSON,简化了数据传输的过程。
-
7. @RestController
-
@RestController是
@Controller
和@ResponseBody
的组合(@ResponseBody会将java对象直接返回写入到响应体中,一般为JSON数据)。 -
使用
@RestController
注解的类会自动被Spring MVC识别为控制器,并将其方法的返回值作为HTTP响应的正文。 -
将对如下示例进行解析:
@RestController @RequestMapping("/user") public class UserController { @GetMapping("/list") public List<User> listUsers() { // 返回用户列表 // 返回值会被自动序列化为JSON格式 } }
- @RestController这个注解表明
UserController
类是一个控制器,并且它的所有方法的返回值都将被序列化为JSON(或其它配置的格式),直接作为HTTP响应的正文返回。
- @RestController这个注解表明
-
什么时候使用@RestController?
- 在Web应用程序中,前端页面可能需要请求用户列表以展示给用户。
- 响应的数据是一个java对象,内容较多时,SpringMVC会自动将返回的对象序列化为JSON,简化了数据传输的过程。