💡 一则也许对你有用的小广告 🏆

欢迎飞飞程序员   ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论

  • 正在进行中的项目:《FFBlog知识付费博客项目》 正在持续更新中,基于 Spring Boot 3.x + JDK 21...,点击查看 ;
  • 《从零开发:FFBlog知识付费博客项目(全栈开发)》 演示链接: https://ffblog.ffcxy.com/  ;

截止目前, 飞飞  正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, Ai系统, CMS系统,在线商城系统,等等 ,欢迎点击围观

摘要
@RestController 就是 @Controller 加 @ResponseBody 的组合,类里所有方法返回值自动写成 JSON,不用逐个加注解。

@RestController 是 Spring MVC 里最常用的注解之一,专门用于前后端分离的 REST API 开发。它是 @Controller + @ResponseBody 的组合,让类里所有方法的返回值都自动转成 JSON。


一、先看它的本质

@RestController 的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller        // ← 继承 @Controller
@ResponseBody      // ← 继承 @ResponseBody
public @interface RestController {
    @AliasFor(annotation = Controller.class)
    String value() default "";
}

所以:

@RestController
public class XxxController { ... }

完全等价于:

@Controller
@ResponseBody
public class XxxController { ... }

二、对比示例:@Controller vs @RestController

示例1:用 @Controller(传统方式,返回页面)

@Controller
public class PageController {

    @GetMapping("/index")
    public String index() {
        return "index";   // 返回视图名,去找 index.html
    }
}
  • 浏览器访问 /index,Spring 会去找 index.html / index.jsp,渲染成 HTML 页面。
  • 返回值是"页面名",不是数据。

示例2:用 @Controller + @ResponseBody(返回 JSON)

@Controller
public class UserController {

    @GetMapping("/user")
    @ResponseBody    // ← 每个方法都要加,很麻烦
    public User getUser() {
        return new User(1L, "张三");
    }
}
  • 返回的是 JSON 数据,不再跳转页面。
  • 每个方法都要写 @ResponseBody,啰嗦。

示例3:用 @RestController(推荐,返回 JSON)

@RestController
public class UserController {

    @GetMapping("/user")
    public User getUser() {   // 不用加 @ResponseBody
        return new User(1L, "张三");
    }
}
  • 整个类所有方法都自动返回 JSON,不用逐个加 @ResponseBody。
  • 这就是前后端分离项目的标准写法。

三者对比

写法 返回值含义 是否需要 @ResponseBody
@Controller 视图名(页面) 不需要(就是跳页面)
@Controller + @ResponseBody JSON 数据 每个方法都要加
@RestController JSON 数据 不用加(类级别已生效)

三、完整可运行示例

1. 定义实体类

public class User {
    private Long id;
    private String username;
    private Integer age;

    // 构造器、getter/setter 省略
    public User(Long id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }
}

2. 写 Controller

@RestController
@RequestMapping("/users")     // 统一路径前缀
public class UserController {

    // 模拟数据库
    private static final Map<Long, User> DB = new HashMap<>();
    static {
        DB.put(1L, new User(1L, "张三", 20));
        DB.put(2L, new User(2L, "李四", 22));
    }

    // ① 查询单个用户:GET /users/1
    @GetMapping("/{id}")
    public Response<User> getUser(@PathVariable Long id) {
        User user = DB.get(id);
        if (user == null) {
            return Response.fail(404, "用户不存在");
        }
        return Response.success(user);
    }

    // ② 查询列表:GET /users
    @GetMapping
    public Response<List<User>> listUsers() {
        return Response.success(new ArrayList<>(DB.values()));
    }

    // ③ 新增用户:POST /users
    @PostMapping
    public Response<User> createUser(@RequestBody User user) {
        DB.put(user.getId(), user);
        return Response.success("创建成功", user);
    }

    // ④ 删除用户:DELETE /users/1
    @DeleteMapping("/{id}")
    public Response<Void> deleteUser(@PathVariable Long id) {
        DB.remove(id);
        return Response.success();
    }
}

3. 前端请求与响应

查询单个用户:

GET /users/1

响应(JSON):

{
  "code": 200,
  "data": { "id": 1, "username": "张三", "age": 20 },
  "message": "请求成功",
  "success": true
}

查询列表:

GET /users

响应:

{
  "code": 200,
  "data": [
    { "id": 1, "username": "张三", "age": 20 },
    { "id": 2, "username": "李四", "age": 22 }
  ],
  "message": "请求成功",
  "success": true
}

新增用户:

POST /users
Content-Type: application/json

{ "id": 3, "username": "王五", "age": 25 }

响应:

{
  "code": 200,
  "data": { "id": 3, "username": "王五", "age": 25 },
  "message": "创建成功",
  "success": true
}

删除用户:

DELETE /users/1

响应:

{
  "code": 200,
  "data": null,
  "message": "请求成功",
  "success": true
}

四、@RestController 常配合的注解

注解 作用 示例
@RequestMapping 类/方法级别的路径映射 @RequestMapping("/users")
@GetMapping GET 请求 @GetMapping("/{id}")
@PostMapping POST 请求 @PostMapping
@PutMapping PUT 请求 @PutMapping("/{id}")
@DeleteMapping DELETE 请求 @DeleteMapping("/{id}")
@PathVariable 取 URL 路径变量 @PathVariable Long id
@RequestParam 取 URL 查询参数 @RequestParam String name
@RequestBody 取请求体 JSON @RequestBody User user
@Validated 参数校验 @Validated @RequestBody User user

一个综合示例:

@RestController
@RequestMapping("/api/articles")
public class ArticleController {

    // GET /api/articles?page=1&size=10
    @GetMapping
    public Response<List<Article>> list(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        return Response.success(articleService.page(page, size));
    }

    // GET /api/articles/5
    @GetMapping("/{id}")
    public Response<Article> detail(@PathVariable Long id) {
        return Response.success(articleService.findById(id));
    }

    // POST /api/articles
    @PostMapping
    public Response<Article> create(@Validated @RequestBody Article article) {
        return Response.success(articleService.save(article));
    }

    // PUT /api/articles/5
    @PutMapping("/{id}")
    public Response<Article> update(@PathVariable Long id,
                                    @RequestBody Article article) {
        article.setId(id);
        return Response.success(articleService.update(article));
    }

    // DELETE /api/articles/5
    @DeleteMapping("/{id}")
    public Response<Void> delete(@PathVariable Long id) {
        articleService.delete(id);
        return Response.success();
    }
}

五、常见误区

误区1:用 @RestController 却想返回页面

@RestController
public class PageController {
    @GetMapping("/index")
    public String index() {
        return "index";   // ❌ 返回的是字符串 "index",不是跳转页面
    }
}
  • 用 @RestController 就没法返回页面了,返回的 "index" 会原样输出。
  • 要返回页面,请用 @Controller。

误区2:以为 @RestController 只能返回 JSON

  • 其实它只是"返回值直接写响应体",具体格式由 HttpMessageConverter 决定。
  • 返回 User → JSON(Jackson 转换)
  • 返回 String → 纯文本
  • 返回 byte[] → 二进制

误区3:类上加了,方法上又加 @ResponseBody

@RestController
public class UserController {
    @GetMapping("/user")
    @ResponseBody    // ← 多余,可省略
    public User getUser() { ... }
}
  • 类上已有 @RestController,方法上不用再加 @ResponseBody。

六、@Controller 和 @RestController 怎么选?

场景 推荐注解
前后端分离,只返回 JSON 数据 @RestController
传统服务端渲染(Thymeleaf/JSP) @Controller
同一个类里既返回页面又返回数据 @Controller + 方法级 @ResponseBody

如今绝大多数新项目都是前后端分离,所以 @RestController 是主流。


七、总结

问题 答案
@RestController 是什么? @Controller + @ResponseBody 的组合注解
干啥用的? 让类的所有方法返回值自动转成 JSON 写响应体
和 @Controller 区别? @Controller 返回视图名(跳页面),@RestController 返回数据(JSON)
还需要写 @ResponseBody 吗? 不用,类级别已生效
能返回页面吗? 不能,要返回页面用 @Controller
最常配什么注解? @RequestMapping、@GetMapping、@RequestBody 等

一句话记住:

@RestController = "这个类里所有方法都返回 JSON 数据",是前后端分离项目 Controller 层的标配注解。 用了它,方法返回 User、List、Response 等对象,都会自动被 Jackson 转成 JSON 返回给前端。

上一篇 Java中的重载和重写有什么区别?
下一篇 SpringBoot框架中@ResponseBody 注解详解

全部评论(0)

头像
😃 😁 😅 😂 😍 😜 😝 🤑 🥵 🥰 😙 😎 😵 😭 😱 😖 🥳 👽 🙈 🤡 😤 💣 💯 💢 ❤️ 👍 👏 👋 👌 🤏 🙏
还没有任何评论哟~
微信扫一扫
微信二维码
微信客服
QQ 咨询
QQ二维码
工作日 9:00 - 18:00 在线
QQ客服
在线工单
提交问题工单,我们会尽快回复处理。
提交工单
在线工单