Spring Boot 中 @RequestBody 的全面解析
- 发布时间:2025-12-14 22:12:38
- 本文热度:浏览 9 赞 0 评论 0
- 文章标签: SpringBoot 后端开发 Web开发
- 全文共1字,阅读约需1分钟
1. 基础概念与核心思想
@RequestBody 是 Spring MVC 中使用频率极高的注解之一,它用于将 HTTP 请求体(Request Body)中的 JSON / XML / 表单数据 自动转换为 Java 对象。初学者最困惑的问题通常是:
- 它与
@RequestParam有什么区别? - 为什么传 JSON 时必须加
@RequestBody? - 为什么不加就接不到数据?
- 底层到底是谁在解析 JSON?
- 到底什么时候用它?
为了完全理解它,我们需要从 原理 → 用途 → 示例 → 实战 的路径来全面剖析。
核心理念
@RequestBody = 接收请求体内容(JSON/XML)并自动反序列化为 Java 对象
底层依赖的是:
HttpMessageConverter(消息转换器)
只要你的项目中有 Jackson(Spring Boot 默认引入),Spring 就能自动把 JSON → Java Bean。
2. 为什么需要 @RequestBody(解决什么痛点)
在没有 @RequestBody 之前,获取 JSON 只能通过原始方式:
BufferedReader reader = request.getReader();
String body = reader.lines().collect(Collectors.joining());
JSONObject json = new JSONObject(body);
痛点:
- 代码冗长
- 手动解析 JSON 容易出错
- Controller 中充满重复逻辑
- 参数多、层级深时异常复杂
- 不支持自动校验(JSR303)
而 @RequestBody 的出现:
- 自动解析 JSON
- 支持复杂嵌套对象
- 自动类型转换
- 配合
@Valid支持 Bean 校验 - 支持集合、泛型、数组
请求体再复杂也能轻松解析。
3. 工作原理(底层机制)
理解原理是避免踩坑的关键。
Spring 处理请求的大概流程如下伪图示:
HTTP Request
↓
DispatcherServlet
↓
HandlerMapping 查找匹配的Controller方法
↓
HandlerAdapter 调用对应方法
↓
参数解析(ArgumentResolver)
↓
如果参数上有 @RequestBody → 使用 HttpMessageConverter 处理
↓
读取请求体(JSON)
↓
反序列化(Jackson)
↓
生成 Java 对象
↓
Controller 方法内部可直接使用
3.1 底层关键组件:HttpMessageConverter
常见的几个转换器:
| 转换器 | 说明 |
|---|---|
MappingJackson2HttpMessageConverter |
JSON 转换器(最常用) |
StringHttpMessageConverter |
文本 / 字符串转换 |
FormHttpMessageConverter |
表单数据转换 |
Jaxb2RootElementHttpMessageConverter |
XML 转换器 |
当 Spring 听到你的 Controller 参数上有:
@RequestBody UserDTO user
它会自动交给 JSON 转换器处理。
4. @RequestBody 的各种使用场景
4.1 接收 JSON 对象
示例代码
前端请求:
{
"username": "zhangsan",
"age": 18
}
Java Bean:
@Data
public class UserDTO {
private String username;
private Integer age;
}
Controller:
@PostMapping("/user/add")
public String addUser(@RequestBody UserDTO user) {
return "接收到用户:" + user.getUsername();
}
4.2 接收 JSON 数组
前端请求:
[
{"username": "zs", "age": 18},
{"username": "ls", "age": 20}
]
Controller:
@PostMapping("/user/list")
public String addUserList(@RequestBody List<UserDTO> users) {
return "收到用户数量:" + users.size();
}
4.3 接收嵌套对象
前端 JSON:
{
"orderId": 1001,
"items": [
{"name": "可乐", "count": 2},
{"name": "面包", "count": 3}
]
}
Java Bean:
@Data
public class OrderItem {
private String name;
private Integer count;
}
@Data
public class OrderDTO {
private Long orderId;
private List<OrderItem> items;
}
4.4 与 @Valid 联合使用
@PostMapping("/user/save")
public String save(@Valid @RequestBody UserDTO user, BindingResult result) {
if (result.hasErrors()) {
return result.getFieldError().getDefaultMessage();
}
return "ok";
}
4.5 接收 Map
@PostMapping("/map")
public Map<String, Object> test(@RequestBody Map<String, Object> map) {
return map;
}
5. 实战案例:用户注册接口(Spring Boot)
用户注册通常包含 JSON 请求:
{
"username": "Tom",
"password": "123456",
"email": "tom@example.com"
}
5.1 Java Bean
@Data
public class RegisterDTO {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
}
5.2 Controller 接口
@RestController
@RequestMapping("/auth")
public class AuthController {
@PostMapping("/register")
public String register(@Valid @RequestBody RegisterDTO dto, BindingResult result) {
if (result.hasErrors()) {
return result.getFieldError().getDefaultMessage();
}
return "注册成功:" + dto.getUsername();
}
}
5.3 application.yml(完整示例)
server:
port: 8080
spring:
jackson:
serialization:
indent_output: true
mvc:
format:
date: yyyy-MM-dd HH:mm:ss
6. 深入理解:@RequestBody vs @RequestParam vs @ModelAttribute
这是很多小白最困惑的问题。
6.1 区别表格(重点)
(根据要求,表格前后必须空一行)
| 注解 | 数据来源 | 常用格式 | 是否必须注解 | 使用场景 |
|---|---|---|---|---|
@RequestBody |
请求体(Body) | JSON/XML | 必须 | JSON 请求、前后端分离 |
@RequestParam |
URL 查询参数 | ?a=1&b=2 | 可选 | 简单参数 |
@ModelAttribute |
表单、URL 参数 | form-data | 可选 | 传统表单提交 |
6.2 判断依据
如果前端发 JSON → 一定要用 @RequestBody
如果是 URL 参数(?name=xxx)→ 用 @RequestParam
如果是 form 表单 → 用 @ModelAttribute(可省略)
7. 常见错误与 Debug 指南
错误 1:Required request body is missing
原因:
- 使用 JSON 请求,但 Controller 没写
@RequestBody
错误示例:
@PostMapping("/add")
public void add(UserDTO user) { } // ❌ user 为 null
正确:
@PostMapping("/add")
public void add(@RequestBody UserDTO user) { } // ✔
错误 2:415 Unsupported Media Type
原因:
- 请求头没有写:
Content-Type: application/json
必须这样写:
curl -H "Content-Type: application/json" -d '{"a":1}' ...
错误 3:JSON parse error
原因:
- JSON 格式语法错误
- 字段类型不匹配(如 age=“abc”)
解决:
- 检查 JSON
- 检查字段类型
错误 4:List 接收失败
若前端发送:
[
{"name":"a"}
]
Controller 必须写:
@RequestBody List<UserDTO> list
不能写:
@RequestBody UserDTO user // ❌
8. 高级用法
8.1 自定义消息转换器
例如使用 Gson:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
GsonHttpMessageConverter gsonConverter = new GsonHttpMessageConverter();
converters.add(gsonConverter);
}
}
8.2 响应体加密 / 解密
可以通过自定义:
- RequestBodyAdvice
- ResponseBodyAdvice
实现 Controller 层透明加密解密。
9. 实战案例:前后端分离的登录接口(完整)
9.1 JSON 请求
{
"username": "admin",
"password": "123456"
}
9.2 Java Bean
@Data
public class LoginDTO {
private String username;
private String password;
}
9.3 Controller
@RestController
@RequestMapping("/login")
public class LoginController {
@PostMapping
public String login(@RequestBody LoginDTO dto) {
if ("admin".equals(dto.getUsername()) && "123456".equals(dto.getPassword())) {
return "登录成功";
}
return "用户名或密码错误";
}
}
10. 作者经验总结
10.1 什么时候必须用 @RequestBody?
- 你使用的是 JSON 请求(前后端分离必用)
- 请牢记:Body 中的数据不会被自动解析,必须使用 @RequestBody
10.2 最常见的坑
- Content-Type 写错
- Controller 参数没加 @RequestBody
- JSON 字段类型不一致
- 嵌套对象字段名错误
10.3 最佳实践
- 所有 JSON 接口都加 @RequestBody
- Bean 使用 @Data
- 开启校验并处理异常
- 全局异常处理,统一返回 JSON
11. 结语
到此我们已经从基础概念、底层原理、使用方法、示例代码、实战案例、错误排查、最佳实践等方面,完整讲解了 @RequestBody。无论是对于新手还是有经验的开发者,只要牢牢掌握这篇内容,就能完全吃透 Spring MVC 中请求体解析的核心机制。
正文到此结束
相关文章
热门推荐
评论插件初始化中...