才知道原来 yaml 传文章是不支持 @ 的,YAML对特殊字符(如@:等)敏感,直接放在字段值中可能导致解析错误。所以传文章一开始搞了好久))


一般来说,我在开发的时候更多使用的是@RestController,而不是@Controller,所以突发奇想研究了以下这两者的区别,方便我在以后的使用中更加清晰。

什么是@RestController,什么是@Controller

首先,@RestController@Controller 都是 Spring Framework 中用于定义控制器的注解。

@Controller 注解标记的类则是传统的控制器类,用于标记处理 HTTP 请求的控制器类。

  • 对于Spring MVC框架中,它用于处理客户端发起的请求,并负责将数据填充到视图模板作为响应。
  • 在使用 @Controller 注解的类中,如果需要返回 JSON、XML 等数据,通常需要在方法上使用 @ResponseBody 注解来指示该方法的返回值要作为响应的主体内容,而不是解析为视图。如果返回的是字符串,Spring 会将其视为视图名称,并通过视图解析器渲染对应的视图。
  • @Controller 标记的类中,方法默认返回的是视图名称,而非实际数据。Spring 会通过视图解析器(ViewResolver) 将视图名称映射到具体的视图模板。

@RestController 是一个组合注解,它结合了 @Controller@ResponseBody 注解的功能(就相当于把两个注解组合在一起)。在使用 @RestController 注解标记的类中,每个方法的返回值都会以 JSON 或 XML 的形式直接写入 HTTP 响应体中,相当于在每个方法上都添加了 @ResponseBody注解。

  • 专门用于 RESTful API 的控制器,直接返回数据(如 JSON、XML),无需视图解析。方法的返回值会自动通过消息转换器(如 Jackson)序列化为 JSON 或其他格式,等价于@Controller + @ResponseBody的组合

总地来说,@RestController 适用于构建 RESTful 风格的 API,其中每个方法的返回值会直接序列化为 JSON 或 XML 数据并发送给客户端。而 @Controller 适用于传统的 MVC 架构,它负责处理请求并返回相应的视图。(@RestController下的方法默认返回的是数据格式@Controller注解标注的类下面的方法默认返回的就是以视图为格式

@RestController@Controller的对比

在 Spring 框架中,@RestController@Controller是两个用于定义控制器的注解,它们的主要区别在于返回值的处理方式

共同点都是用来表示 Spring 某个类是否可以接收 HTTP 请求

区别则是,@Controller能返回指定的页面,@RestController不行,他是直接返回数据

特性 @Controller @RestController
默认返回类型 视图名称(需视图解析器) 直接返回数据(JSON/XML)
注解组合 单独使用,需配合@ResponseBody返回数据 等价于@Controller + @ResponseBody
适用场景 传统 MVC 应用,需要渲染页面 RESTful API,直接返回数据
示例返回值处理 return "user-view"; → 渲染 user-view.jsp return user; → 返回 JSON {"id":1,"name":"John"}

当设计 RESTful API 时,一般的原则是:

  • 如果客户端希望获取数据(例如 JSON、XML),则返回数据。
    • 当你在开发一个单页应用的后端接口时,前端通常会通过 Ajax 请求获取数据(例如 JSON),然后使用 JavaScript 动态更新页面。在这种情况下,你应该返回数据(例如使用 @ResponseBody 注解)。
  • 如果客户端希望展示数据(例如 HTML 页面),则返回视图。
    • 当你需要为前端渲染 HTML 页面时,需要返回视图。视图可以包含动态生成的数据,但最终会经过服务器端模板引擎的处理,形成最终的 HTML 页面。

对于 @Controller

这个注解主要用于标记 MVC 控制器类。在默认情形下,被它标记的类中的方法返回值会被当作视图名称来处理,Spring 会依据这个名称去查找对应的视图模板,进而渲染出 HTML 页面。

  • 传统的 Spring MVC 控制器,用于处理 HTTP 请求并返回视图(如 JSP、Thymeleaf 模板等)。
  • 返回值处理
    • 如果返回的是字符串,Spring 会将其视为视图名称,并通过视图解析器渲染对应的视图。
    • 如果需要返回 JSON、XML 等数据,需要配合@ResponseBody注解使用。
  • 选择 @Controller 场景
    • 传统 Web 应用,需要返回 HTML 页面。
    • 使用 Thymeleaf、JSP 等模板引擎渲染视图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
public class UserController {
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.getUserById(id);
model.addAttribute("user", user);
return "user-details"; // 返回视图名称,对应user-details.jsp或Thymeleaf模板
}

@GetMapping("/api/users/{id}")
@ResponseBody // 显式声明返回JSON数据
public User getUserApi(@PathVariable Long id) {
return userService.getUserById(id); // 直接返回对象,自动序列化为JSON
}
}

对于 @RestController

  • 专门用于 RESTful API 的控制器,直接返回数据(如 JSON、XML),无需视图解析。
  • 返回值处理
    • 方法的返回值会自动通过消息转换器(如 Jackson)序列化为 JSON 或其他格式。
    • 等价于@Controller + @ResponseBody的组合。
  • 选择 @RestController 场景
    • 开发 RESTful API,如前后端分离的项目。
    • 服务间调用(如微服务),返回 JSON/XML 格式数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController // 相当于@Controller + @ResponseBody
@RequestMapping("/api")
public class UserRestController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id); // 直接返回对象,自动序列化为JSON
}

@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = userService.saveUser(user);
return ResponseEntity.created(URI.create("/api/users/" + savedUser.getId())).body(savedUser);
}
}

@ResponseBody注解让方法返回值作为响应内容

在使用 @Controller 注解标记的类中,默认情况下,方法的返回值会被解析为一个视图名称,并寻找与该名称匹配的视图进行渲染。这意味着返回的结果会被解析为一个 HTML 页面或者模板引擎所需的数据。

但是有时候需要将方法的返回值直接作为响应的主体内容,而不是解析为视图。为了实现这个目的,我们可以在方法上使用 @ResponseBody 注解。

@ResponseBody 注解表示方法的返回值应该直接写入 HTTP 响应体中,而不是被解析为视图。它告诉 Spring MVC 框架将方法的返回值序列化为特定格式(如 JSON、XML 等)并作为响应的主体内容返回给客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class MixedController {
@GetMapping("/page")
public String showPage() {
return "page"; // 返回视图
}

@GetMapping("/data")
@ResponseBody
public Map<String, String> getData() {
return Map.of("key", "value"); // 返回数据
}
}
  • @Controller + @ResponseBody:适用于在一个控制器里同时处理视图和数据的情况

有时候并不需要返回视图,只需要一组数据,这样在方法加上一个@ResponseBody,就可以让返回的格式转换为数据格式

@Controller 方法通常需要配合 @ResponseBody 注解,才能将返回值作为响应的主体内容。

传统的springMVC一般就需要直接返回视图,而现在新兴的前端技术vue在项目中为前后端分离的架构,前端框架负责处理数据和渲染页面,而后端 API 则负责提供数据即可,所以对返回视图的要求也就比较少了