@RequestBody
你可以使用 @RequestBody 注解让请求主体被读取,并通过 HttpMessageConverter 反序列化为 Java 对象。
使用示例
java
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// 自动将 JSON/XML 请求体转换为 Account 对象
}kotlin
@PostMapping("/accounts")
fun handle(@RequestBody account: Account) {
// 自动将 JSON/XML 请求体转换为 Account 对象
}核心特性
- 转换机制:依赖于
HttpMessageConverter。Spring 会根据请求头的Content-Type选择合适的转换器(如 Jackson 处理 JSON)。 - 校验支持:可以配合
@Valid或@Validated使用。验证失败默认抛出MethodArgumentNotValidException(400 错误)。 - 配置:可以通过 MVC Java 配置中的
configureMessageConverters来自定义转换行为。
注意
表单数据(application/x-www-form-urlencoded)应使用 @RequestParam 读取,而不是 @RequestBody。因为 Servlet API 在访问请求参数时会解析主体,导致 @RequestBody 无法再次读取。
补充教学
1. 为什么 REST API 离不开它?
在 REST 架构中,资源的状态通常以 JSON 格式在请求体中传输。@RequestBody 是 Spring MVC 处理这种交互的核心。它让你能够以面向对象的方式编写接口,而不需要关心底层 JSON 具体的解析细节。
2. 局部错误处理
如果你不想因为校验失败直接让 Spring 抛出 400 错误,可以注入 BindingResult:
java
public void create(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
// 在这里自定义返回逻辑,比如返回 200 及错误详情
}
}3. @RequestBody 的不可重复读取性
HttpServletRequest 的输入流(InputStream)默认只能读取一次。
- 陷阱:如果你在 Filter 里读了请求体,Controller 里的
@RequestBody就会拿不到数据。 - 对策:如果确实需要多次读取(例如用于日志记录或签名验证),你需要使用
ContentCachingRequestWrapper装饰原生的 Request 对象。