15.springboot-控制器处理参数传递
22.springMVC
Spring MVC 是非常著名的 Web 应用框架,现在的大多数 Web 项目都采用 Spring MVC。它与 Spring 有着紧 密的关系。是 Spring 框架中的模块,专注 Web 应用,能够使用 Spring 提供的强大功能,IoC , Aop 等等。
Spring MVC 框架是底层是基于 Servlet 技术。遵循 Servlet 规范,Web 组件 Servlet,Filter,Listener 在 SpringMVC 中都能使用。同时 Spring MVC 也是基于 MVC 架构模式的,职责分离,每个组件只负责自己的功能,组件解耦。
学习 Spring MVC 首先具备 Servlet 的知识,关注 MVC 架构的 M、V、C 在 Spring MVC 框架中的实现。掌握了 这些就能熟练的开发 Web 应用。
Spring Boot 的自动配置、按约定编程极大简化,提高了 Web 应用的开发效率
控制器
控制器一种有 Spring 管理的 Bean 对象,赋予角色是“控制器”。作用是处理请求,接收浏览器发送过来的
参数,将数据和视图应答给浏览器或者客户端 app 等。
控制器是一个普通的 Bean,使用@Controller 或者@RestController 注释。@Controller 被声明为@Component。
所以他就是一个 Bean 对象。
- 有@Controller, @RestController注解的类叫做控制器, 项目中控制器有很多
一般相关的业务是一个控制器, 比如订单的处理工作, 订单的控制OrderController.
- @Controller, @RestController区别
@RestController包含了@Controller的功能,同时加入了@ResponseBody的注解。
表示当前控制器类中的所有方法,都会默认加入@ResponseBody的功能。 方法的返回值是数据可以通过
HttpServletResponse输出给浏览器,请求方法。
@Controller注解有@Component的功能, 控制器类对象是Spring容器管理的。
- 定制控制器方法
1.方法上面的@RequestMapping(value=“请求的uri地址”) :表示这个uri的请求由当前方法处理
@GetMapping, @PostMapping, @PutMapping , @DeleteMapping
2.控制器方法的形参,接收请求的参数,多种方法接收参数
3.控制器方法的返回值,表示应答结果,给请求的结果(数据,视图)
匹配请求路径
SpringMVC 支持多种策略,匹配请求路径到控制器方法。AntPathMatcher 、 PathPatternParser
从 SpringBoot3 推荐使用 PathPatternParser 策略。比之前 AntPathMatcher 提示 6-8 倍吞吐量。
PathPatternParser 中有关 uri 的定义 通配符:
? : 一个字符
* : 0 或多个字符。在一个路径段中匹配字符
**:匹配 0 个或多个路径段,相当于是所有
正则表达式: 支持正则表达式
RESTFul 的支持路径变量
{变量名}
{myname:[a-z]+}: 正则 a-z 的多个字面,路径变量名称“myname”。@PathVariable(“myname”)
{*myname}: 匹配多个路径一直到 uri 的结尾
? 单个字符
package com.yanyu.demo1.controller;import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author yanyu666_508200729@qq.com* @Date 2025/4/20 0:48* @description:*/@RestController
public class PathController {
// ? 代表单个字符@GetMapping("/path1/d?mo")public String path1(HttpServletRequest request){return request.getRequestURI();//获取请求的 uri}}
- 测试
- 浏览器
- idea
- resources
- 不同的请求 ### 隔开
* 0个或者多个字符
package com.yanyu.demo1.controller;import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author yanyu666_508200729@qq.com* @Date 2025/4/20 0:48* @description:*/@RestController
public class PathController {
// ? 代表单个字符@GetMapping("/path1/d?mo")public String path1(HttpServletRequest request){return request.getRequestURI();//获取请求的 uri}
// 0 多个字符@GetMapping("/path2/*.png")public String path2(HttpServletRequest request){return request.getRequestURI();//获取请求的 uri}}
**
// 所有字符、所有路径@GetMapping("/path3/**")public String path3(HttpServletRequest request){return request.getRequestURI();//获取请求的 uri}
{* 变量名}
/ {*id}@GetMapping("/path4/{*id}")
// 以 path4 开头,直接结尾,变量名字是 idpublic String path4(@PathVariable("id") String myId, HttpServletRequest request){return request.getRequestURI() + ",变量参数:" + myId;//获取请求的 uri}
// 注意:@GetMapping("/order/{*id}/{*date}")无效的, {*..}后面不能在有匹配规则了
{变量名:正则表达式}
/** \w:匹配一个“单词字符”,包括:
所有大小写字母(a-z 和 A-Z)。
所有数字(0-9)。
下划线(_)。
+:表示前面的字符(或字符集)出现一次或多次。* */@GetMapping("/path5/{fname:\\w+}.png")
// 以 path4 开头,直接结尾,变量名字是 idpublic String path5(@PathVariable("fname") String myId, HttpServletRequest request){return request.getRequestURI() + ",变量参数:" + myId;//获取请求的 uri}
唯一路径
推荐使用
@RequestMapping
@RequestMapping:用于将 web 请求映射到控制器类的方法。此方法处理请求。可用在类上或方法上。
在类和方法同时组合使用。
重要的属性
value:别名 path 表示请求的 uri, 在类和方法方法同时使用 value,方法上的继承类上的 value 值。
method:请求方式,支持 GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE。
值为:RequestMethod[] method() , RequestMethod 是 enum 类型。
快捷注解
@GetMapping: 表示 get 请求方式的@RequestMapping
@PostMapping:表示 post 请求方式的@RequestMapping
@PutMapping:表示 put 请求方式的@RequestMapping
@DeleteMapping: 表示 delete 请求方式的@RequestMapping
对于请求方式 get,post,put,delete 等能够 HttpMethod 表示,Spring Boot3 之前是 enum,Spring Boot3 是 class
控制器方法参数类型与可用返回值类型
- 参数类型
完整 https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments
- 返回值
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-return-types
接收请求参数
用户在浏览器中点击按钮时,会发送一个请求给服务器,其中包含让服务器程序需要做什么的参数。 这些
参数发送给控制器方法。控制器方法的形参列表接受请求参数。
接受参数方式:
请求参数与形参一一对应,适用简单类型。形参可以有合适的数据类型,比如 String,Integer ,int 等。
对象类型,控制器方法形参是对象,请求的多个参数名与属性名相对应。
@RequestParam 注解,将查询参数,form 表单数据解析到方法参数,解析 multipart 文件上传。
@RequestBody,接受前端传递的 json 格式参数。
HttpServletRequest 使用 request 对象接受参数, request.getParameter(“…”)
@RequestHeader ,从请求 header 中获取某项值
解析参数需要的值,SpringMVC 中专门有个接口来干这个事情,这个接口就是:HandlerMethodArgumentResolver,
中文称呼:处理器方法参数解析器,说白了就是解析请求得到 Controller 方法的参数的值。
请求参数与形参一一对应
package com.yanyu.demo1.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author yanyu666_508200729@qq.com* @Date 2025/4/21 21:46* @description:*/
@RestController
public class ParameterController {
// p1?name=yanyu&age= 20@GetMapping("p1")public String p1(String name,Integer age){return "前端传递的参数是:" + name + " ," + age ;}
}
- 应用:一一对应,适合接收简单类型数据String,int,long,double,float, 参数数量少
对象来接收
-
使用对象接收参数, 要求对象的属性名称和请求中参数名一样, 属性有set方法,类有无参数构造方法
-
一一对应与对象接收还可以混合使用
-
准备映射参数的实体类
package com.yanyu.demo1.vo;/*** @Author yanyu666_508200729@qq.com* @Date 2025/4/21 21:56* @description: 映射传递参数的实体类,属性名 与 传递的参数要一致*/
public class Student {private String name;private Integer age;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
@GetMapping("p2")public String p2(Student student){
// 可以通过对象,执行各种服务return student.toString();}
HttpServletRequest
使用HttpServletRequest接收参数
@GetMapping("p3")
// 和以前的一样public String p3(HttpServletRequest request){String name = request.getParameter("name");String age = request.getParameter("age");return "HttpServletRequest接收参数" + name + " ," + age;}
@RequestParam
@RequestParam
是 Spring MVC 中的一个注解,用于将 HTTP 请求中的参数绑定到控制器方法的参数上。它非常适用于处理 GET 请求的查询参数或 POST 请求的表单数据。以下是 @RequestParam
的详细用法和示例。
1. 基本用法
1.1 单个参数绑定
@RequestParam
可以将请求中的参数值绑定到方法的参数上。如果请求中存在对应的参数,Spring 会自动将其值传递给方法参数。
示例代码:
java
复制
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ExampleController {@GetMapping("/greet")public String greet(@RequestParam String name) {return "Hello, " + name + "!";}
}
请求示例:
GET /greet?name=John
返回结果:
Hello, John!
2. 参数默认值
如果请求中没有提供某个参数,可以通过 defaultValue
属性为该参数指定默认值。
示例代码:
java
复制
@GetMapping("/greet")
public String greet(@RequestParam(defaultValue = "Guest") String name) {return "Hello, " + name + "!";
}
请求示例:
GET /greet
返回结果:
Hello, Guest!
3. 参数是否必需
通过 required
属性可以指定某个参数是否必需。如果 required = true
,且请求中没有提供该参数,Spring 会抛出 MissingServletRequestParameterException
异常。
示例代码:
java
复制
@GetMapping("/greet")
public String greet(@RequestParam(required = true) String name) {return "Hello, " + name + "!";
}
请求示例:
GET /greet
返回结果:
400 Bad Request: Required String parameter 'name' is not present
@GetMapping("p4")public String p4(@RequestParam(value = "name", required = true) String name,
// 把请求的 name 传递给 String name, 参数必须有@RequestParam(value = "age", required = false, defaultValue = "22") Integer age) {
// 参数可以没有 没有的情况下,默认值 22return "@RequestParam传递的参数:" + name + "," + age;}
@RequestHeader
@RequestHeader
是 Spring MVC 提供的一个注解,用于将 HTTP 请求头中的值绑定到控制器方法的参数上。它允许开发者以声明式的方式获取和使用请求头中的信息。以下是 @RequestHeader
的常见用法:
- 获取指定的请求头
可以通过指定 name
或 value
属性来获取请求头中的特定值。例如:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader("Accept-Encoding") String encoding) {// 使用 encoding...return "Handled request with encoding: " + encoding;
}
如果请求头中不存在指定的头,可以通过设置 required = false
和 defaultValue
来指定默认值:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader(value = "Accept-Encoding", required = false, defaultValue = "gzip") String encoding) {// 使用 encoding...return "Handled request with encoding: " + encoding;
}
- 获取所有请求头
可以将参数类型设置为 Map<String, String>
或 HttpHeaders
来获取所有请求头。例如:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader Map<String, String> headers) {// 使用 headers...return "Handled request with headers: " + headers;
}
或者:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader HttpHeaders headers) {// 使用 headers...return "Handled request with headers: " + headers;
}
- 类型转换
如果目标方法参数类型不是 String
,Spring 会自动应用类型转换。例如:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader("Keep-Alive") long keepAlive) {// 使用 keepAlive...return "Handled request with keepAlive: " + keepAlive;
}
- 处理多个请求头
可以同时使用多个 @RequestHeader
注解来处理多个请求头。例如:
java
复制
@GetMapping("/example")
public String handleRequest(@RequestHeader("Accept-Encoding") String encoding,@RequestHeader("Keep-Alive") long keepAlive) {// 使用 encoding 和 keepAlive...return "Handled request with encoding: " + encoding + " and keepAlive: " + keepAlive;
}
注意事项
- 如果请求头中不存在指定的头,且未设置默认值,Spring 会抛出
MissingRequestHeaderException
。 - 当使用
HttpHeaders
类型时,可以方便地访问和操作请求头。
通过 @RequestHeader
注解,可以方便地访问和处理 HTTP 请求头中的信息,从而增强 Web 应用程序的功能。
// 与 @RequestParam 一样@GetMapping("p5")public String p5(@RequestHeader(value = "Accept",required = false,defaultValue = "default") String accept){return accept;}
@RequestBody
@RequestBody
是 Spring MVC 中的一个注解,用于将 HTTP 请求的正文(body)绑定到控制器方法的参数上。它通常用于处理 POST 或 PUT 请求,这些请求通常包含 JSON 或 XML 格式的数据。Spring 使用 HttpMessageConverter
接口来自动将请求正文反序列化为 Java 对象。
1. 基本用法
1.1 接收 JSON 数据
假设客户端发送一个 JSON 格式的请求正文,你可以使用 @RequestBody
将其绑定到一个 Java 对象上。
示例代码:
java
复制
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ExampleController {@PostMapping("/user")public String createUser(@RequestBody User user) {return "User created: " + user.getName();}
}
User 类:
java
复制
public class User {private String name;private String email;// Getters and Setterspublic String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}
请求示例:
复制
POST /user
Content-Type: application/json{"name": "John Doe","email": "john.doe@example.com"
}
返回结果:
User created: John Doe
2. 接收 XML 数据
@RequestBody
也可以用于接收 XML 格式的请求正文。你需要确保配置了支持 XML 的 HttpMessageConverter
(如 Jaxb2RootElementHttpMessageConverter
)。
示例代码:
java
复制
@PostMapping("/user")
public String createUser(@RequestBody User user) {return "User created: " + user.getName();
}
User 类(使用 JAXB 注解):
java
复制
import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement
public class User {private String name;private String email;// Getters and Setterspublic String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}
请求示例:
复制
POST /user
Content-Type: application/xml<User><name>John Doe</name><email>john.doe@example.com</email>
</User>
返回结果:
User created: John Doe
package com.yanyu.demo1.vo;/*** @Author yanyu666_508200729@qq.com* @Date 2025/4/21 21:56* @description: 映射传递参数的实体类,属性名 与 传递的参数要一致*/
public class Student {private String name;private Integer age;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
@PostMapping("p6")public String p6(@RequestBody Student student){return student.toString();}
idea测试
POST http://localhost:8080/p6
Content-Type: application/json{"name":"烟雨","age":20}<> 2025-04-21T224727.200.txt
Reader-InputStream
Reader
或 InputStream 读取请求体的数据, 适合 post 请求体的各种数据。具有广泛性
@PostMapping("p7")public String p7(Reader reader){StringBuffer stringBuffer = new StringBuffer("");// 使用字符流 读取 请求体数据BufferedReader bufferedReader = new BufferedReader(reader);var line = "";while (true){try {if (!((line = bufferedReader.readLine() ) != null)) break;} catch (IOException e) {throw new RuntimeException(e);}stringBuffer.append(line);}return stringBuffer.toString();}
接收多个值的数组参数
例如:批量传入 id ,根据 id 进行数据的删除操作
@GetMapping("p8")public String getAllId(Integer [] id){/** 使用 Arrays.stream(id) 将数组转换为流。
使用 toList() 方法将流转换为列表。* */List<Integer> list = Arrays.stream(id).toList();return list.toString();}