摘要
详解 SpringBoot 中 @ResponseBody 注解的作用与 @RestController 的关系,以及它和 @RequestBody、统一响应类的配合,帮你搞懂返回值如何被转成 JSON 写入响应体,还有常见的踩坑点和底层 HttpMessageConverter 转换原理。
一句话:@ResponseBody 告诉 Spring:"这个方法的返回值不要当成页面名去跳转,而是直接转成数据(JSON/XML)写进 HTTP 响应体返回给前端。"
它是 Spring MVC 里非常核心的一个注解,理解它对搞懂前后端分离项目至关重要。
一、先理解"没有它"会发生什么
Spring MVC 默认遵循"返回字符串 = 视图名"的规则。
场景:不加 @ResponseBody
@Controller
public class UserController {
@GetMapping("/hello")
public String hello() {
return "hello"; // Spring 认为你要跳转到 hello.html / hello.jsp
}
}
Spring 拿到 "hello",会去找一个叫 hello 的视图(页面),然后渲染返回 HTML。
👉 返回值被当成了"页面名字"。
场景:加上 @ResponseBody
@Controller
public class UserController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "hello"; // 直接把 "hello" 这个字符串写进响应体
}
}
浏览器收到的是纯文本 hello,不是页面跳转。
👉 返回值被当成了"要返回的数据"。
二、两种模式的对比
不加 @ResponseBody | 加 @ResponseBody | |
|---|---|---|
| 返回值含义 | 视图名(页面) | 响应数据 |
| 处理方式 | 找视图渲染 HTML | 转成 JSON/XML 写入响应体 |
| 典型返回 | "index" → 跳转 index.html | User 对象 → {"id":1,...} |
| 适用场景 | 传统服务端渲染(JSP/Thymeleaf) | 前后端分离(REST API) |
三、@ResponseBody 到底做了什么?
它触发 Spring 的 HttpMessageConverter(消息转换器) 机制:
方法返回 User 对象
↓
@ResponseBody 拦截
↓
HttpMessageConverter 把 User 转成 JSON
↓
写入 HTTP 响应体
↓
前端收到 { "id": 1, "name": "张三" }
关键点:对象 → JSON 的转换就是靠它完成的(底层通常用 Jackson)。
四、@RestController = @Controller + @ResponseBody
写 REST API 时,如果每个方法都加 @ResponseBody 太啰嗦,Spring 提供了组合注解:
// 这两个写法完全等价
@Controller
@ResponseBody
public class UserController { ... }
// 等价于
@RestController
public class UserController { ... }
@RestController 源码本质就是:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Controller
@ResponseBody // ← 内置了这个
public @interface RestController {
}
所以在前后端分离项目里,Controller 上写 @RestController,方法上就不用再加 @ResponseBody 了。
五、和你之前那个 Response 类的关系
还记得你写的统一响应封装吗?它俩配合起来是这样工作的:
@RestController // ← 相当于每个方法都加了 @ResponseBody
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public Response<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
return Response.success(user); // 返回 Response 对象
}
}
执行流程:
1. 方法返回 Response<User> 对象
↓
2. @RestController(含 @ResponseBody)生效
↓
3. HttpMessageConverter 把 Response 对象转成 JSON
↓
4. 写入 HTTP 响应体
↓
前端收到:
{
"code": 200,
"data": { "id": 1, "name": "张三" },
"message": "请求成功",
"success": true
}
👉 Response 负责"包装数据",@ResponseBody 负责"把包装好的对象转成 JSON 发出去"。两者各司其职。
六、常见搭配的注解
| 注解 | 作用 | 方向 |
|---|---|---|
@ResponseBody | 返回值 → 响应体(出) | 后端 → 前端 |
@RequestBody | 请求体 → 方法参数(入) | 前端 → 后端 |
@RequestParam | URL 查询参数 → 方法参数 | 前端 → 后端 |
@PathVariable | URL 路径变量 → 方法参数 | 前端 → 后端 |
一个完整例子:
@RestController
public class UserController {
@PostMapping("/user")
public Response<User> create(@RequestBody User user) {
// @RequestBody:把前端传来的 JSON 转成 User 对象
User saved = userService.save(user);
return Response.success(saved);
// @RestController 隐含 @ResponseBody:把 Response 转成 JSON 返回
}
}
@RequestBody:进来的 JSON → Java 对象@ResponseBody:出去的 Java 对象 → JSON
一进一出,刚好配一对。
七、底层原理(了解即可)
Spring 判断返回值怎么处理,靠的是 RequestResponseBodyMethodProcessor:
- 检查方法/类上有没有
@ResponseBody - 有 → 遍历所有
HttpMessageConverter,找到能处理该返回类型的转换器 - 用
MappingJackson2HttpMessageConverter(Jackson)把对象转成 JSON - 写入
HttpServletResponse的输出流
常见的 HttpMessageConverter:
| 转换器 | 处理类型 |
|---|---|
MappingJackson2HttpMessageConverter | JSON(最常用) |
StringHttpMessageConverter | String |
ByteArrayHttpMessageConverter | byte[] |
Jaxb2RootElementHttpMessageConverter | XML |
八、容易踩的坑
坑1:忘了加 @ResponseBody,返回对象被当成视图名
@Controller
public class UserController {
@GetMapping("/user")
public User getUser() {
return new User(); // ❌ 报错:找不到名为 User 的视图
}
}
解决:加 @ResponseBody 或改用 @RestController。
坑2:@Controller + 返回 String 想返回 JSON 字符串
@Controller
public class C {
@GetMapping("/msg")
@ResponseBody
public String msg() {
return "{\"name\":\"张三\"}"; // 返回的是字符串,不是对象
}
}
如果想返回对象自动转 JSON,返回类型应该是 User 而不是 String。
九、总结
| 问题 | 答案 |
|---|---|
@ResponseBody 是什么? | 让方法返回值直接写入响应体(转 JSON) |
| 不加会怎样? | 返回值被当成视图名,去找页面跳转 |
和 @RestController 关系? | @RestController = @Controller + @ResponseBody |
| 底层靠什么转换? | HttpMessageConverter(通常是 Jackson) |
和 @RequestBody 区别? | 一个管"出"(响应),一个管"入"(请求) |
和你写的 Response 类关系? | Response 包装数据,@ResponseBody 把包装好的对象转成 JSON |
一句话记住:
@ResponseBody就是"把 Java 对象变成 JSON 发出去"的开关;@RestController是它的懒人版,一次性给整个类都打开。
在前后端分离项目里,你几乎每个 Controller 都会用到它(或直接用 @RestController)。
全部评论(0)
还没有任何评论哟~