@RestController 详解:从源码到实践

@RestController 详解:从源码到实践

一、什么是 @RestController?

@RestController 是 Spring 4.0 引入的注解,它是 @Controller@ResponseBody 的组合。用于标记一个类为 RESTful 风格的控制器,类中所有方法的返回值直接作为 HTTP 响应体返回,无需通过视图解析器渲染。

二、与 @Controller 的本质区别

传统 Web 应用中,@Controller 配合视图解析器(如 Thymeleaf、JSP)使用。方法返回字符串代表视图名称,Spring 根据名称找到对应的模板文件,渲染成 HTML 后返回给浏览器。这个过程中,数据通过 Model 对象传递到视图层。

java 复制代码
@Controller
public class UserController {
    @GetMapping("/user")
    public String getUser(Model model) {
        model.addAttribute("name", "张三");
        return "userView"; // 返回视图名,渲染 userView.html
    }
}

@RestController 改变了这套逻辑。它把 @ResponseBody 的作用范围从单个方法提升到整个类,所有方法返回值跳过视图解析器,直接写入 HTTP 响应体。

java 复制代码
@RestController
public class UserController {
    @GetMapping("/user")
    public User getUser() {
        return new User("张三"); // 直接输出 JSON
    }
}

@RestController 的源码定义:

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(annotation = Controller.class)
    String value() default "";
}

从源码可以看出,@RestController 本身被 @Controller@ResponseBody 标记。@AliasFor 允许你像 @Controller 一样指定 Bean 名称,例如 @RestController("userController")

三、底层工作原理

Spring MVC 的核心是 DispatcherServlet。当一个 HTTP 请求到达时,DispatcherServlet 通过 HandlerMapping 找到能处理该请求的 HandlerMethod(即 Controller 中的方法),然后委托给 HandlerAdapter 执行。

@RestController 的方法由 RequestMappingHandlerAdapter 处理。这个适配器内部维护了一个 HandlerMethodReturnValueHandler 列表,每个处理器负责处理不同类型的返回值。

对于 @RestController,关键处理器是 RequestResponseBodyMethodProcessor。它的处理流程:

  1. 执行 Controller 方法,得到返回对象
  2. 遍历已注册的 HttpMessageConverter 列表
  3. 根据返回类型和请求的 Accept 头,选择能处理该类型的转换器
  4. 调用转换器的 write() 方法,将对象序列化并写入 HttpServletResponse 的输出流

HttpMessageConverter 是 Spring 处理对象序列化的核心接口。常见实现:

转换器 作用
MappingJackson2HttpMessageConverter 使用 Jackson 将对象序列化为 JSON
MappingJackson2XmlHttpMessageConverter 将对象序列化为 XML
StringHttpMessageConverter 处理字符串返回值
ByteArrayHttpMessageConverter 处理字节数组
ResourceHttpMessageConverter 处理文件资源

@RestController 返回 User 对象时,请求头 Accept: application/json 存在,RequestMappingHandlerAdapter 会选择 MappingJackson2HttpMessageConverter,最终输出 {"id":1,"name":"张三"}

四、返回 String 的陷阱

@RestController 返回 String 时,不会自动添加双引号变成 JSON 格式。因为 StringHttpMessageConverter 的优先级高于 MappingJackson2HttpMessageConverter,它直接把字符串作为 text/plain 写入响应体。

java 复制代码
@RestController
public class TestController {
    @GetMapping("/test")
    public String test() {
        return "hello"; // 返回纯文本 "hello",不是 JSON
    }
}

如果希望返回 JSON 格式的字符串,几种处理方式:

  • 手动拼接 JSON 字符串(不推荐)
  • 返回 Object 类型,让 Jackson 处理
  • 使用 ResponseEntity 并指定 Content-Type

五、ResponseEntity 进阶用法

ResponseEntity 允许精确控制 HTTP 响应的状态码、响应头和响应体,是 RESTful API 开发中更推荐的返回方式。

java 复制代码
@GetMapping("/user/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    if (user == null) {
        return ResponseEntity.notFound().build();
    }
    return ResponseEntity.ok(user);
}

ResponseEntity 的常见构建方式:

java 复制代码
// 200 OK 带响应体
return ResponseEntity.ok(user);

// 201 Created(常用于 POST 请求)
return ResponseEntity.status(HttpStatus.CREATED).body(user);

// 204 No Content(常用于 DELETE 请求)
return ResponseEntity.noContent().build();

// 404 Not Found
return ResponseEntity.notFound().build();

// 自定义状态码和响应头
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
    .header("X-Error-Code", "1001")
    .body(errorInfo);

六、扩展:自定义消息转换器

当默认的 JSON 序列化不满足需求时,可以自定义 HttpMessageConverter

例如,需要处理 application/x-protobuf 格式的请求和响应,可以编写一个 ProtobufHttpMessageConverter 并注册到 Spring 容器中。

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MappingJackson2HttpMessageConverter());
        converters.add(new ProtobufHttpMessageConverter());
        // 注意顺序,先添加的优先级更高
    }
}

七、总结

@RestController 是 Spring Boot 前后端分离架构的基石注解。它通过组合 @Controller@ResponseBody,将方法返回值直接转换为 HTTP 响应体,底层依赖 HttpMessageConverter 完成序列化。

理解它的原理,关键在于理清 DispatcherServletHandlerAdapterHandlerMethodReturnValueHandlerHttpMessageConverter 这条调用链。掌握了这些,你不仅会用 @RestController,更能在遇到序列化异常、返回格式不符合预期时,快速定位问题源头。

相关推荐
边境悍匪1 小时前
springboot常用注解
java·spring boot·学习
李昊哲小课2 小时前
Spring Boot 4 旅游主题实战教程 阶段四:缓存与底层进阶
spring boot·redis·缓存·性能优化·log4j·旅游·性能
QQ_21696290963 小时前
【源码编号:project93375】SpringBoot汽车维修管理信息系统:客户车辆、维修预约、工单派发、配件结算全流程实战
java·spring boot·后端·汽车·springboot·需求分析
xcl09253 小时前
流浪宠物领养管理系统开发实战:从需求分析到落地的完整指南
java·spring boot·需求分析·宠物
2601_962063234 小时前
【Spring Boot】掌握 Spring 事务:隔离级别与传播机制解读与应用
spring boot·spring·adb
gis开发之家4 小时前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端
李昊哲小课5 小时前
Spring Boot 4 旅游主题实战教程 阶段二:Web 开发基础
前端·spring boot·旅游
2601_962063976 小时前
Spring Boot拦截器(Interceptor)详解
java·spring boot·后端
李昊哲小课6 小时前
SpringBoot4 云端咖啡站 阶段一:起步与基础
spring boot