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
,我们仍然可以显式指定响应的内容类型。通过 @RequestMapping
的 produces
属性就能实现,@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 仓库 获取。