的核Spring MVC 接收请求参数心是通过注解绑定请求中的数据(URL 路径、请求头、请求体、表单、查询参数等)到控制器方法的参数上,不同注解适配不同的参数来源场景。以下是全场景的注解分类、使用方式和核心注意事项,覆盖日常开发 99% 的场景:
一、核心注解总览(按参数来源分类)
| 注解 | 作用场景 | 核心说明 |
|---|---|---|
@RequestParam |
获取 URL 查询参数 / 表单参数(application/x-www-form-urlencoded) | 绑定单个参数,支持必填、默认值、参数名映射 |
@PathVariable |
获取 URL 路径中的占位符参数(RESTful 风格) | 绑定路径中的动态值(如 /user/{id} 中的 id) |
@RequestBody |
获取请求体中的 JSON/XML 数据(application/json) | 绑定请求体到 Java 对象,仅能在方法中用一次 |
@RequestHeader |
获取 HTTP 请求头中的参数 | 绑定单个请求头(如 Content-Type、Token) |
@CookieValue |
获取客户端 Cookie 中的值 | 绑定指定名称的 Cookie 值 |
@ModelAttribute |
绑定请求参数到 JavaBean(表单 / 查询参数) | 自动封装多个参数到实体类,支持级联属性 |
@RequestPart |
接收文件上传 / 复杂请求体(multipart/form-data) | 绑定文件或 JSON 格式的 Part 数据(替代@RequestParam处理文件) |
| 无注解(默认绑定) | 简单类型参数(与请求参数名一致) | 仅适用于参数名与请求参数名完全匹配的简单场景(不推荐,可读性差) |
二、详细使用示例(附场景说明)
1. @RequestParam:查询参数 / 表单参数(最常用)
适用于 GET 请求的 URL 查询参数(?name=xxx&age=18)、POST 表单提交(application/x-www-form-urlencoded)。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ParamController {
// 基础用法:绑定单个查询参数
@GetMapping("/user/query")
public String queryUser(
// name:请求参数名(与URL中的参数名一致)
// required:是否必填(默认true,不传则报400错误)
// defaultValue:默认值(仅当required=false时生效)
@RequestParam(name = "name", required = false, defaultValue = "匿名") String username,
@RequestParam("age") Integer userAge // 简写:name可省略,默认取参数名
) {
return "用户名:" + username + ",年龄:" + userAge;
}
// 接收多个同名参数(如 ?hobby=篮球&hobby=足球)
@GetMapping("/user/hobby")
public String queryHobby(@RequestParam List<String> hobby) {
return "爱好:" + String.join(",", hobby);
}
}
请求示例:
GET /user/query?name=张三&age=20 → 用户名:张三,年龄:20
GET /user/query?age=20 → 用户名:匿名,年龄:20(使用默认值)
GET /user/hobby?hobby=篮球&hobby=足球 → 爱好:篮球,足球
2. @PathVariable:RESTful 路径参数
适用于 URL 路径中的动态占位符(如 /user/123 中的 123 是用户 ID),RESTful 风格必备。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RestControllerDemo {
// 单个路径参数
@GetMapping("/user/{id}")
public String getUserById(@PathVariable("id") Long userId) {
return "用户ID:" + userId;
}
// 多个路径参数 + 非必选(Spring 5.3+支持)
@GetMapping("/order/{orderId}/item/{itemId}")
public String getOrderItem(
@PathVariable Long orderId, // 简写:参数名与占位符一致时,可省略括号内的名称
@PathVariable(required = false) Long itemId // 非必选(需确保URL匹配,如 /order/123/item/ 或 /order/123/item)
) {
return "订单ID:" + orderId + ",商品ID:" + itemId;
}
}
请求示例:
GET /user/123 → 用户ID:123
GET /order/456/item/789 → 订单ID:456,商品ID:789
GET /order/456/item → 订单ID:456,商品ID:null(非必选)
3. @RequestBody:请求体 JSON/XML 参数
适用于 POST/PUT 请求的请求体(application/json 格式),是前后端分离的核心注解。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
// 实体类
class User {
private String name;
private Integer age;
// getter/setter省略
}
@RestController
public class JsonController {
// 绑定JSON请求体到Java对象
@PostMapping("/user/save")
public String saveUser(@RequestBody User user) {
return "保存用户:" + user.getName() + ",年龄:" + user.getAge();
}
// 绑定原始JSON字符串
@PostMapping("/user/raw")
public String rawJson(@RequestBody String jsonStr) {
return "原始JSON:" + jsonStr;
}
}
请求示例(Postman/Apifox):
-
请求方法:POST
-
Content-Type:application/json
-
请求体:
{ "name": "李四", "age": 25 } -
响应:
保存用户:李四,年龄:25
⚠️ 注意:
- 一个方法中只能有一个
@RequestBody(请求体只能解析一次); - 若请求体为空且
required=true(默认),会报 400 错误; - 需确保项目引入 JSON 解析依赖(如
jackson-databind,Spring Boot 已内置)。
4. @RequestHeader:请求头参数
适用于获取 HTTP 请求头中的数据(如 Token、Content-Type、User-Agent 等)。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HeaderController {
// 获取单个请求头
@GetMapping("/header/token")
public String getToken(@RequestHeader("Authorization") String token) {
return "Token:" + token;
}
// 获取所有请求头
@GetMapping("/header/all")
public String getAllHeaders(@RequestHeader java.util.Map<String, String> headers) {
return "请求头:" + headers.toString();
}
}
请求示例:
GET /header/token
Header:Authorization: Bearer 123456 → 响应:Token:Bearer 123456
5. @CookieValue:Cookie 参数
适用于获取客户端携带的 Cookie 值(如登录态、用户标识)。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CookieController {
@GetMapping("/cookie/user")
public String getCookie(
@CookieValue(value = "userId", required = false, defaultValue = "0") String userId
) {
return "Cookie中的用户ID:" + userId;
}
}
请求示例:
GET /cookie/user
Cookie:userId=789 → 响应:Cookie中的用户ID:789
6. @ModelAttribute:绑定到 JavaBean(表单 / 查询参数)
适用于多个请求参数自动封装到实体类(替代多个 @RequestParam),支持级联属性(如 user.address.province)。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;
// 实体类(支持级联)
class UserForm {
private String name;
private Integer age;
private Address address; // 级联属性
// getter/setter省略
}
class Address {
private String province;
private String city;
// getter/setter省略
}
@RestController
public class FormController {
// 绑定表单参数到UserForm
@PostMapping("/user/form")
public String submitForm(@ModelAttribute UserForm userForm) {
return "用户:" + userForm.getName() +
",地址:" + userForm.getAddress().getProvince() + "-" + userForm.getAddress().getCity();
}
}
请求示例(表单提交):
- 请求方法:POST
- Content-Type:application/x-www-form-urlencoded
- 参数:
name=王五&age=30&address.province=广东&address.city=深圳 - 响应:
用户:王五,地址:广东-深圳
⚠️ 注意:@ModelAttribute 可省略,直接写实体类参数(Spring 会自动绑定),效果一致。
7. @RequestPart:文件上传 / 复杂 Part 参数
适用于 multipart/form-data 类型的请求(文件上传、混合表单 + JSON),替代 @RequestParam 处理文件。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class FileController {
// 单文件上传
@PostMapping("/file/upload")
public String uploadFile(
@RequestPart("file") MultipartFile file, // 绑定文件
@RequestPart("desc") String description // 绑定普通表单参数
) {
return "文件名:" + file.getOriginalFilename() + ",描述:" + description;
}
// 多文件上传 + JSON参数混合
@PostMapping("/file/batch")
public String batchUpload(
@RequestPart("files") MultipartFile[] files,
@RequestPart("user") User user // 绑定JSON格式的Part参数(Content-Type: application/json)
) {
return "上传文件数:" + files.length + ",用户:" + user.getName();
}
}
请求示例(文件上传):
- 请求方法:POST
- Content-Type:multipart/form-data
- 表单项:
- file:选择本地文件(如 test.txt)
- desc:测试文件
- 响应:
文件名:test.txt,描述:测试文件
8. 无注解默认绑定
当参数名与请求参数名完全一致时,可省略注解,Spring 会自动绑定(简单场景可用,不推荐复杂场景,可读性差)。
@GetMapping("/user/simple")
public String simpleParam(String name, Integer age) {
return "用户名:" + name + ",年龄:" + age;
}
请求示例:
GET /user/simple?name=赵六&age=35 → 用户名:赵六,年龄:35
三、特殊场景处理
1. 日期类型参数绑定
Spring MVC 默认不支持 yyyy-MM-dd 等自定义日期格式,需配置转换器或注解指定格式:
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
public class DateController {
// 方式1:@DateTimeFormat指定格式
@GetMapping("/date/query")
public String queryDate(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date createTime) {
return "创建时间:" + createTime;
}
// 方式2:全局配置日期转换器(推荐,避免每个参数加注解)
// 配置类中注册Converter:
// @Bean
// public Converter<String, Date> dateConverter() {
// return new Converter<>() {
// @Override
// public Date convert(String source) {
// return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
// }
// };
// }
}
2. 数组 / 集合参数绑定
-
数组:直接用数组类型接收(如
String[] hobby); -
List:必须用
@RequestParam注解(Spring 无法直接绑定无注解的 List); -
Map:用
@RequestParam Map<String, String>接收所有查询参数 / 表单参数。@GetMapping("/param/collection")
public String collectionParam(
String[] hobby, // 数组
@RequestParam List<String> tags, // List必须加@RequestParam
@RequestParam Map<String, String> allParams // 所有参数
) {
return "爱好:" + Arrays.toString(hobby) + ",标签:" + tags + ",所有参数:" + allParams;
}
四、常见问题与避坑指南
-
参数名不匹配:
- 原因:注解中
name/value与请求参数名不一致; - 解决:核对参数名,或开启 Spring MVC 的参数名匹配(Spring Boot 默认开启)。
- 原因:注解中
-
@RequestBody 报 415 Unsupported Media Type:
- 原因:请求头
Content-Type不是application/json,或未引入 JSON 解析依赖; - 解决:设置正确的 Content-Type,确保项目有
jackson-databind依赖。
- 原因:请求头
-
@PathVariable 报 404:
- 原因:URL 路径与
@GetMapping中的路径模板不匹配(如占位符数量不一致); - 解决:核对 URL 和路径模板(如
/user/{id}对应/user/123,而非/user?id=123)。
- 原因:URL 路径与
-
日期参数绑定报 400:
- 原因:日期格式不匹配,Spring 无法解析;
- 解决:用
@DateTimeFormat或全局日期转换器。
-
文件上传报 413 Request Entity Too Large:
-
原因:上传文件大小超过 Spring / 服务器限制;
-
解决:配置文件大小限制(Spring Boot):
spring: servlet: multipart: max-file-size: 10MB # 单个文件大小 max-request-size: 50MB # 总请求大小
-
五、总结
| 场景 | 推荐注解 | 核心注意事项 |
|---|---|---|
| URL 查询参数 / 表单参数 | @RequestParam | 注意必填性、默认值,List 需显式注解 |
| RESTful 路径参数 | @PathVariable | 路径模板与 URL 匹配,非必选需 Spring 5.3+ |
| JSON 请求体 | @RequestBody | 仅能使用一次,Content-Type 需为 application/json |
| 请求头 / Cookie | @RequestHeader/@CookieValue | 注意参数名与头 / Cookie 名一致 |
| 文件上传 /multipart 请求 | @RequestPart | 替代 @RequestParam,支持文件和 JSON 混合 |
| 多参数封装到实体类 | @ModelAttribute | 支持级联属性,可省略注解 |
核心原则:显式注解优于隐式绑定,复杂场景优先使用对应注解(如 JSON 用 @RequestBody,路径参数用 @PathVariable),提升代码可读性和可维护性。