Skip to content

@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 对象。

Based on Spring Framework.