Spring MVC @RequestBody 注解怎么用?接收什么格式的数据?

@RequestBody 注解的作用

@RequestBody 将方法上的参数绑定到 HTTP 请求的 Body(请求体)的内容上

当客户端发送一个包含数据的请求体(通常在 POST, PUT, PATCH 请求中)时,@RequestBody 告诉 Spring MVC 读取这个请求体,并使用已注册的 HttpMessageConverter 将其内容**反序列化(Deserialize)**为一个 Java 对象。

简单来说,它允许我们直接将请求中发送的 JSON、XML 或其他格式的数据映射到一个 Java 对象(通常是一个 POJO - Plain Old Java Object)。

@RequestBody 的工作机制

  1. 读取请求体: Spring MVC 获取 HTTP 请求的输入流。
  2. 检查 Content-Type Header: 查看请求头中的 Content-Type,例如 application/jsonapplication/xml。这个 Header 会告诉服务器客户端发送的是什么格式的数据。
  3. 选择 HttpMessageConverter: Spring MVC 会查找已注册的、能够处理该 Content-Type 的请求体内容转换为方法参数指定类型的 HttpMessageConverter
  4. 反序列化: HttpMessageConverter 读取请求体内容,并将其转换为目标 Java 对象。
  5. 参数绑定: 转换后的 Java 对象会传递给带有 @RequestBody 注解的方法参数。

常用场景:接收 JSON 或 XML 数据

@RequestBody 最常用于接收客户端发送的 JSON 或 XML 数据,尤其是在构建 RESTful API 时。

示例:接收 JSON 数据

假设客户端发送一个 POST 请求到 /api/users,请求体包含以下 JSON 数据:

{
  "username": "john.doe",
  "email": "john.doe@example.com",
  "age": 30
}

并且请求头中设置了 Content-Type: application/json

我们可以定义一个对应的 Java POJO:

// User.java (POJO)
public class User {
    private String username;
    private String email;
    private int age;

    // Getters and Setters (必需,供 Jackson 等库使用)
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    @Override
    public String toString() {
        return "User{" +
               "username='" + username + '\'' +
               ", email='" + email + '\'' +
               ", age=" + age +
               '}';
    }
}

然后在 Controller 中这样使用 @RequestBody

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody User user) {
        // 此时,Spring MVC 已经使用 HttpMessageConverter (通常是 Jackson)
        // 将请求体中的 JSON 数据转换为了一个 User 对象实例 'user'
        System.out.println("Received user: " + user);

        // 在这里可以进行保存用户等业务逻辑...
        // userService.save(user);

        return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully: " + user.getUsername());
    }
}

所需依赖

Spring MVC 依赖 HttpMessageConverter 来实现 @RequestBody 的功能。

  1. 处理 JSON (最常用):

    • 依赖库: Jackson Databind (jackson-databind) 是 Spring Boot 和 Spring MVC 处理 JSON 的默认库。
    • 如何添加: 如果使用 Spring Boot,spring-boot-starter-web starter 会自动包含 jackson-databind。通常不需要手动添加它。
    • Maven 示例 (如果未使用 Spring Boot Starter 或需要特定版本):
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <!-- <version>...</version> --> <!-- Spring Boot 管理版本 -->
      </dependency>
      
    • 替代库: 虽然不常用,但也可以配置使用其他 JSON 库,如 Gson (com.google.code.gson:gson) 或 JSON-B。
  2. 处理 XML:

    • 依赖库:
      • JAXB (Java Architecture for XML Binding): 这是 Java 标准库的一部分(直到 Java 10,Java 11 及以后需要单独添加依赖)。Spring 对 JAXB 有内建支持。
      • Jackson XML extension (jackson-dataformat-xml): 这是 Jackson 提供的用于处理 XML 的模块,与处理 JSON 的方式非常相似,通常更受欢迎,因为它与 Jackson 的其他功能(如注解)集成得更好。
    • 如何添加 (Jackson XML): 如果你想使用 Jackson 处理 XML,需要手动添加 jackson-dataformat-xml 依赖。spring-boot-starter-web 包含它。
    • Maven 示例 (Jackson XML):
      <dependency>
          <groupId>com.fasterxml.jackson.dataformat</groupId>
          <artifactId>jackson-dataformat-xml</artifactId>
           <!-- <version>...</version> --> <!-- Spring Boot 管理版本 -->
      </dependency>
      
    • POJO 注解: 如果使用 JAXB 或 Jackson XML,需要在 POJO 上添加特定的注解(如 @XmlRootElement, @XmlElement for JAXB,或者 Jackson 也可以使用 JAXB 注解或其自己的注解)映射 XML 结构。不过,对于简单的结构,Jackson XML 也能在没有额外注解的情况下工作。

示例:Controller 处理 XML (假设已添加 jackson-dataformat-xml)

如果客户端发送 Content-Type: application/xml 和以下 XML 请求体:

<User>
  <username>jane.doe</username>
  <email>jane.doe@example.com</email>
  <age>28</age>
</User>

上面的 createUser 方法无需修改(只要 User POJO 的结构匹配),Spring MVC 会自动选择 MappingJackson2XmlHttpMessageConverter(如果 jackson-dataformat-xml 在 classpath 中)来处理请求。

关键点和注意事项

  1. Content-Type Header: 客户端必须发送正确的 Content-Type 请求头,以便 Spring MVC 知道如何解析请求体并选择合适的 HttpMessageConverter。如果 Content-Type 不匹配或缺失,通常会导致 HTTP 415 (Unsupported Media Type) 错误。
  2. 必需性: @RequestBody 标注的参数默认是必需的。如果请求体为空或无法转换为目标类型,会抛出 HttpMessageNotReadableException,通常导致 HTTP 400 (Bad Request) 错误。
  3. 唯一性: 一个 Controller 方法只能有一个参数使用 @RequestBody 注解,因为一个 HTTP 请求只有一个请求体。
  4. 不要与 @RequestParam 混淆: @RequestParam 用于获取 URL 查询参数或表单数据(application/x-www-form-urlencoded),而 @RequestBody 用于获取整个请求体的内容(通常是 JSON 或 XML)。
  5. Validation: 通常会结合 Java Bean Validation API (JSR 380/303) 使用 @RequestBody。通过在 @RequestBody 参数前添加 @Valid 注解,可以自动触请求体反序列化后的对象的校验。
import javax.validation.Valid;
import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;

// User.java (带校验注解)
public class User {
    @NotBlank(message = "Username cannot be blank")
    private String username;

    @NotBlank
    @Email(message = "Invalid email format")
    private String email;

    @Min(value = 0, message = "Age must be positive")
    private int age;
    // ... Getters and Setters ...
}

// Controller 方法
@PostMapping
public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
    // 如果校验失败,Spring 会自动返回 400 Bad Request
    // 如果校验成功,代码继续执行
    System.out.println("Received valid user: " + user);
    // ...
    return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully: " + user.getUsername());
}

要使 @Valid 生效,需要添加 spring-boot-starter-validation 依赖(如果使用 Spring Boot)或相应的 hibernate-validator 依赖。

总结

  • @RequestBody 用于将 HTTP 请求的完整 Body 反序列化为一个 Java 对象。
  • 主要用于接收 POST, PUT, PATCH 请求中的 JSONXML 数据。
  • 依赖于 HttpMessageConverter 和相应的库(如 jackson-databind for JSON,jackson-dataformat-xml or JAXB for XML)。
  • spring-boot-starter-web 默认包含 Jackson JSON 支持。处理 XML 需要手动添加依赖。
  • 客户端必须发送正确的 Content-Type Header。
  • 一个方法只能有一个 @RequestBody 参数。
  • 常与 @Valid 结合进行自动数据校验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值