Spring Boot 中 @Controller与 @RestController的区别及 404 错误解析
在开发 Spring Boot 应用时,经常会遇到一个问题:明明写了接口方法,但访问时却返回:
{"timestamp": "2025-08-24 11:28:59","status": 404,"error": "Not Found","message": "No message available","path": "/api/keyword/"
}
很多初学者会以为是路径错了,其实很多情况下是 注解类型使用不当 导致的。本文就结合一个关键字查询接口示例,来分析原因和解决方案。
1️⃣ 问题复现
假设你写了一个 Controller:
@Controller
@RequestMapping("/api/keyword")
public class KeywordController {@GetMapping("/{id}")public Result<Keyword> getById(@PathVariable int id) {return keywordService.getKeywordById(id);}@GetMappingpublic Result<List<Keyword>> getAll() {return keywordService.getAll();}
}
前端请求:
GET /api/keyword/
结果报 404 错误。
2️⃣ 原因分析
-
@Controller
是传统的 MVC 控制器 注解,用于返回 视图(HTML、JSP、Thymeleaf 页面等)。 -
当你在方法中直接返回对象(如
Result<Keyword>
)时,@Controller
并不会自动将对象序列化为 JSON。 -
访问
/api/keyword/
时:- Spring 尝试解析返回值,找对应的视图模板(比如
Result<Keyword>
对应的页面) - 找不到对应模板 → 返回 404(No message available)
- Spring 尝试解析返回值,找对应的视图模板(比如
所以问题是 返回类型无法被处理。
3️⃣ 解决方案
方案 1:使用 @ResponseBody
在每个方法上加 @ResponseBody
:
@Controller
@RequestMapping("/api/keyword")
public class KeywordController {@GetMapping("/{id}")@ResponseBodypublic Result<Keyword> getById(@PathVariable int id) {return keywordService.getKeywordById(id);}@GetMapping@ResponseBodypublic Result<List<Keyword>> getAll() {return keywordService.getAll();}
}
@ResponseBody
告诉 Spring 将返回值序列化为 JSON,而不是去找视图模板。
方案 2:直接使用 @RestController
(推荐)
@RestController
@RequestMapping("/api/keyword")
public class KeywordController {@GetMapping("/{id}")public Result<Keyword> getById(@PathVariable int id) {return keywordService.getKeywordById(id);}@GetMappingpublic Result<List<Keyword>> getAll() {return keywordService.getAll();}
}
@RestController
=@Controller + @ResponseBody
,自动处理返回值为 JSON。- 更适合做 RESTful 接口,不需要返回视图页面。
- 前端直接请求
/api/keyword
或/api/keyword/1
就不会再报 404。
4️⃣ 总结
注解 | 功能 | 使用场景 |
---|---|---|
@Controller | MVC 控制器,返回视图 | 页面渲染(HTML、Thymeleaf、JSP) |
@RestController | REST 控制器,返回 JSON | 接口服务(REST API) |
关键点:
- 如果返回对象而不是页面,必须让 Spring 知道要序列化 →
@ResponseBody
或@RestController
- 避免误用
@Controller
返回 JSON,否则会出现 404(找不到视图)
5️⃣ 建议
- 对于 纯后端接口(返回 JSON 数据),统一用
@RestController
,代码简洁。 - 对于 传统 MVC 页面,使用
@Controller
+ 模板引擎(Thymeleaf/JSP)。 - 避免前端请求路径和控制器映射不一致,尤其注意
/
和空路径。 - 如果接口返回对象,请确认返回值已经被序列化,否则会出现类似 404 的错误。