1. 引言

本文将深入探讨 Spring 框架中两个核心注解:@RequestBody@ResponseBody。对于有经验的 Java 开发者来说,这两个注解是构建 RESTful API 的基础工具,理解它们的机制能帮你避免不少踩坑。

2. @RequestBody 注解

简单粗暴地说,**@RequestBody 注解的作用是将 HTTP 请求体自动映射到 Java 对象上**,实现请求内容的反序列化。

先来看个典型的控制器方法示例:

@PostMapping("/request")
public ResponseEntity postController(
  @RequestBody LoginForm loginForm) {
 
    exampleService.fakeAuthenticate(loginForm);
    return ResponseEntity.ok(HttpStatus.OK);
}

Spring 会根据请求的 Content-Type 自动将 JSON 数据反序列化为指定的 Java 类型。关键点在于:被 @RequestBody 注解的参数类型必须与客户端发送的 JSON 结构完全匹配

public class LoginForm {
    private String username;
    private String password;
    // getters/setters...
}

这里 LoginForm 对象完美对应了请求体中的 JSON 结构。用 CURL 测试一下:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data 
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/spring-boot-rest/post/request"

✅ 这就是 Spring REST API 与前端交互的标准姿势,Angular/React 等框架发送的 JSON 请求都能被优雅处理。

3. @ResponseBody 注解

@ResponseBody 注解则完全相反:它告诉 Spring 将返回的对象自动序列化为 JSON 并写入 HTTP 响应体

假设我们有个自定义响应对象:

public class ResponseTransfer {
    private String text; 
    
    // standard getters/setters
}

对应的控制器实现:

@Controller
@RequestMapping("/post")
public class ExamplePostController {

    @Autowired
    ExampleService exampleService;

    @PostMapping("/response")
    @ResponseBody
    public ResponseTransfer postResponseController(
      @RequestBody LoginForm loginForm) {
        return new ResponseTransfer("Thanks For Posting!!!");
     }
}

在浏览器控制台或 Postman 中会看到这样的响应:

{"text":"Thanks For Posting!!!"}

⚠️ 记住:**使用 @RestController 时不需要再单独加 @ResponseBody**,因为 Spring 已经默认帮你处理了。

3.1. 设置响应内容类型

即使使用 @ResponseBody,我们仍然可以显式指定响应的内容类型。通过 @RequestMappingproduces 属性就能实现@PostMapping 等注解也支持这个参数。

先添加一个返回 JSON 的接口:

@PostMapping(value = "/content", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseTransfer postResponseJsonContent(
  @RequestBody LoginForm loginForm) {
    return new ResponseTransfer("JSON Content!");
}

这里用了 MediaType.APPLICATION_JSON_VALUE 常量,也可以直接写 "application/json"

再添加一个同路径但返回 XML 的接口:

@PostMapping(value = "/content", produces = MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public ResponseTransfer postResponseXmlContent(
  @RequestBody LoginForm loginForm) {
    return new ResponseTransfer("XML Content!");
}

现在响应内容完全取决于请求头中的 Accept 参数。用 CURL 验证下:

请求 JSON 响应:

curl -i \ 
-H "Accept: application/json" \ 
-H "Content-Type:application/json" \ 
-X POST --data 
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/spring-boot-rest/post/content"

响应:

HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 20 Feb 2020 19:43:06 GMT

{"text":"JSON Content!"}

请求 XML 响应:

curl -i \
-H "Accept: application/xml" \
-H "Content-Type:application/json" \
-X POST --data
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/spring-boot-rest/post/content"

响应:

HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Thu, 20 Feb 2020 19:43:19 GMT

<ResponseTransfer><text>XML Content!</text></ResponseTransfer>

4. 总结

本文通过实际代码演示了 @RequestBody@ResponseBody 的核心用法,包括:

@RequestBody 自动将请求体反序列化为 Java 对象
@ResponseBody 自动将返回对象序列化为 JSON 响应
✅ 通过 produces 属性灵活控制响应内容类型

对于经验丰富的开发者来说,这些注解的机制并不复杂,但掌握细节能帮你少走弯路。完整代码示例可在 GitHub 仓库 获取。


原始标题:Spring's RequestBody and ResponseBody Annotations