在开发 Spring Boot 应用时,经常会遇到一个问题:明明写了接口方法,但访问时却返回:
json
{
"timestamp": "2025-08-24 11:28:59",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/keyword/"
}
很多初学者会以为是路径错了,其实很多情况下是 注解类型使用不当 导致的。本文就结合一个关键字查询接口示例,来分析原因和解决方案。
1️⃣ 问题复现
假设你写了一个 Controller:
java
@Controller
@RequestMapping("/api/keyword")
public class KeywordController {
@GetMapping("/{id}")
public Result<Keyword> getById(@PathVariable int id) {
return keywordService.getKeywordById(id);
}
@GetMapping
public 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
:
java
@Controller
@RequestMapping("/api/keyword")
public class KeywordController {
@GetMapping("/{id}")
@ResponseBody
public Result<Keyword> getById(@PathVariable int id) {
return keywordService.getKeywordById(id);
}
@GetMapping
@ResponseBody
public Result<List<Keyword>> getAll() {
return keywordService.getAll();
}
}
@ResponseBody
告诉 Spring 将返回值序列化为 JSON,而不是去找视图模板。
方案 2:直接使用 @RestController
(推荐)
java
@RestController
@RequestMapping("/api/keyword")
public class KeywordController {
@GetMapping("/{id}")
public Result<Keyword> getById(@PathVariable int id) {
return keywordService.getKeywordById(id);
}
@GetMapping
public 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 的错误。