乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

RestController

本章紧接 @Controller 的视图渲染模式。在现代 Web 开发中,前后端分离已成为主流——前端(Vue/React)通过 AJAX 调用后端 API,后端只返回 JSON 数据,不再渲染 HTML 页面。@RestController 正是为这种场景设计的组合注解,它让每个方法的返回值直接序列化到响应体。理解 @RestController,就理解了 Spring MVC 的 RESTful API 开发模式。


定义与作用

@RestController 是 Spring 4.0 引入的类级组合注解,它的职责可以用一句话概括:标记一个类为 RESTful 风格的控制器,使其所有方法的返回值直接通过 HttpMessageConverter 序列化写入 HTTP 响应体。

@RestController 的源码定义非常简洁:

@Controller
@ResponseBody
public @interface RestController {
}

它等价于同时标注 @Controller 和 @ResponseBody。这意味着:

  • 类被注册为 Spring MVC 控制器(具备 @Controller 的所有特性)
  • 类的每个方法默认都带有 @ResponseBody(返回值不走 ViewResolver)

生活类比:快递直发 vs 中转仓储

  • @Controller 像传统电商:商品(数据)先送到仓库(ViewResolver),打包成精美礼盒(HTML 页面),再发给客户。客户收到的是完整页面。
  • @RestController 像快递直发:商品(JSON 数据)直接打包发货,不经过仓库中转。客户(前端框架)收到 raw 数据,自己决定如何展示。

核心原理

@Controller vs @RestController 的处理流程对比

图解:

  • @Controller 的返回值进入 ViewResolver 流程,最终生成 HTML
  • @RestController 的返回值进入 HttpMessageConverter 流程,最终生成 JSON/XML
  • 两者在 HandlerMapping 查找、HandlerAdapter 调用阶段完全一致,区别只在返回值处理阶段

使用场景决策流程


适用位置与常用属性

@RestController 是类级注解,没有额外属性,但通常与以下注解配合使用:

配合使用的注解

注解作用与 @RestController 的关系
@RequestMapping声明请求映射规则标注在类或方法上
@GetMapping处理 GET 请求@RequestMapping(method=GET) 的简写
@PostMapping处理 POST 请求@RequestMapping(method=POST) 的简写
@PutMapping处理 PUT 请求@RequestMapping(method=PUT) 的简写
@DeleteMapping处理 DELETE 请求@RequestMapping(method=DELETE) 的简写
@PathVariable绑定 URL 路径变量RESTful URL 参数提取
@RequestBody绑定请求体到对象JSON 反序列化

@Controller vs @RestController 对比表

对比维度@Controller@RestController
注解组成@Component 的特化@Controller + @ResponseBody
方法默认行为返回值作为视图名返回值序列化到响应体
返回 String 时解析为视图名直接作为文本内容返回
返回对象时尝试解析为视图名(通常 404)序列化为 JSON
适用架构传统 MVC(后端渲染页面)前后端分离(RESTful API)
HTTP 响应类型text/htmlapplication/json
模板引擎需要(Thymeleaf/JSP)不需要

完整示例

场景

飞翔科技开发新版员工管理系统,前端使用 Vue 3 框架,后端只提供 RESTful API。后端工程师小崔使用 @RestController 开发所有接口。

控制器代码

package com.feixiang.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    // 容器已注入该 Bean,本教程不展开 Service 实现
    @Autowired
    private EmployeeService employeeService;

    // 查询所有员工
    @GetMapping
    public List<Employee> listAll() {
        return employeeService.findAll();
    }

    // 根据 ID 查询员工
    @GetMapping("/{id}")
    public Employee getById(@PathVariable Long id) {
        return employeeService.findById(id);
    }

    // 创建员工
    @PostMapping
    public Employee create(@RequestBody Employee employee) {
        return employeeService.save(employee);
    }

    // 更新员工
    @PutMapping("/{id}")
    public Employee update(@PathVariable Long id,
                           @RequestBody Employee employee) {
        return employeeService.update(id, employee);
    }

    // 删除员工
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        employeeService.delete(id);
    }
}

HTTP 请求示例 1:查询员工列表

curl -X GET http://localhost:8080/api/employees \
  -H "Accept: application/json"

实际响应:

[
  {
    "id": 1001,
    "name": "张伟",
    "department": "技术部",
    "position": "高级工程师"
  },
  {
    "id": 1002,
    "name": "李娜",
    "department": "市场部",
    "position": "市场经理"
  }
]

分析:

  • listAll() 返回 List<Employee>
  • @RestController 使 @ResponseBody 对所有方法生效
  • MappingJackson2HttpMessageConverter 自动将 List 序列化为 JSON 数组
  • 响应头 Content-Type: application/json

HTTP 请求示例 2:创建新员工

curl -X POST http://localhost:8080/api/employees \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "王强",
    "department": "技术部",
    "position": "初级工程师"
  }'

实际响应:

{
  "id": 1003,
  "name": "王强",
  "department": "技术部",
  "position": "初级工程师"
}

分析:

  • @RequestBody 将请求体 JSON 反序列化为 Employee 对象
  • create() 返回保存后的 Employee
  • @RestController 确保返回值自动序列化为 JSON
  • 前端 Vue 应用可直接将响应数据绑定到页面

易错场景与面试考点

误区一:@RestController 下返回 String 被当作视图名

错误认知:"@RestController 的某个方法返回 String,Spring MVC 会去找同名视图。"

纠正:@RestController 对所有方法都生效了 @ResponseBody,返回 String 时直接作为文本内容写入响应体,不会走 ViewResolver。

@RestController
public class TestController {

    @GetMapping("/hello")
    public String hello() {
        return "hello"; // 浏览器看到纯文本 "hello",不是视图名
    }
}

如果需要返回视图名,必须使用 @Controller,或在方法上显式去掉 @ResponseBody(但类级 @RestController 无法局部取消)。

误区二:混合使用 @Controller 和 @RestController

错误认知:"一个项目里可以同时用 @Controller 和 @RestController,随便混用没问题。"

纠正:虽然技术上可以混用,但架构上应该统一:

  • 前后端分离项目:全部使用 @RestController
  • 传统服务端渲染项目:全部使用 @Controller
  • 混合项目(少量页面 + 大量 API):使用 @Controller,在需要返回 JSON 的方法上单独加 @ResponseBody
// 混合项目的推荐做法
@Controller
public class MixedController {

    // 返回页面
    @GetMapping("/page")
    public String page() {
        return "page";
    }

    // 返回 JSON
    @GetMapping("/api/data")
    @ResponseBody
    public Data data() {
        return dataService.get();
    }
}

面试高频:@Controller 和 @RestController 的区别与选择

标准回答:

  • @Controller 是 Spring MVC 的 Web 层注解,方法返回值默认作为视图名由 ViewResolver 解析为 HTML 页面
  • @RestController 是 @Controller + @ResponseBody 的组合注解,所有方法返回值默认通过 HttpMessageConverter 序列化为 JSON/XML 写入响应体
  • 选择依据:前后端分离项目用 @RestController,传统服务端渲染项目用 @Controller
  • @RestController 下返回 String 直接作为文本内容,不会解析为视图名

小结

@RestController 是 Spring MVC 开发 RESTful API 的首选注解,它通过组合 @Controller 和 @ResponseBody,让所有方法的返回值直接序列化到响应体。在前后端分离架构中,它是后端控制器的标准写法。

本章与全局的关系:本章讲解了 @RestController 的数据直写模式。下一章"RequestMapping"将深入讲解请求映射的核心注解 @RequestMapping,它是所有 HTTP 方法映射注解的元注解。

上一页
Controller
下一页
RequestMapping