Spring REST接口GetMapping未匹配,请求返回404及HTML问题排查
一、为什么请求返回404?
你的请求出现404,大概率是以下几个原因叠加或单独导致的:
端口不匹配
你的curl命令用了9200端口,但Spring Boot默认的服务端口是8080,除非你在application.properties/application.yml里显式配置了server.port=9200,否则你的请求根本没打到Spring Boot应用上,自然会返回404。先确认服务启动的端口,再调整curl命令的端口号。Repository查询语法错误(HQL误用表名)
Spring Data JPA的@Query注解默认使用HQL,而HQL是基于实体类名和实体字段的,不是数据库表名和列名。你现在写的FROM grocery_items是数据库表名,正确的应该用实体类名GroceryItem:// 修正后的Repository代码 interface GroceryItemPersistor extends CrudRepository<GroceryItem, Long> { @Query("FROM GroceryItem WHERE groceryItemName = :name") GroceryItem findByName(@Param("name") String name); @Query("FROM GroceryItem") List<GroceryItem> getAllGroceries(); }这里还要注意:参数对应的是实体类的字段名(比如
groceryItemName,而不是数据库列名grocery_item_name),否则会引发查询错误,可能导致端点无法正常工作。Controller方法缺少return语句
你的GroceryItemResource里的getAllGroceries()方法只调用了持久层方法,但没有返回结果:// 错误写法 @GetMapping List<GroceryItem> getAllGroceries() { groceryItemPersistor.getAllGroceries(); // 没有return }正确的写法应该加上
return:@GetMapping List<GroceryItem> getAllGroceries() { return groceryItemPersistor.getAllGroceries(); }虽然这个问题本身不会直接导致404,但如果方法因为缺少return编译失败,应用可能无法正常启动;如果是运行时的疏漏,也会导致端点返回异常,间接引发错误跳转。
二、为什么Spring返回HTML而不是JSON?
你看到的HTML响应,是因为Spring的错误处理机制进入了循环,无法找到合适的JSON错误视图:
从日志里的No mapping found for HTTP request with URI [/error] in DispatcherServlet和Error page loop /error可以看出:当请求出现404时,Spring会尝试转发到默认的/error端点来处理错误,但你的应用里没有正确映射这个端点,Tomcat就返回了它默认的HTML错误页面。
正常情况下,Spring Boot的spring-boot-starter-web依赖会自动配置BasicErrorController,它会根据请求的Accept头返回对应的格式(JSON或HTML)。但如果出现以下情况,就会失效:
- 你自定义了错误处理逻辑,覆盖了默认的
ErrorController - 应用启动时因为前面的Repository语法错误,导致自动配置的错误控制器没有正常加载
- 请求的
Accept头虽然指定了application/json,但错误处理流程因为循环无法走到返回JSON的逻辑
快速修复步骤
- 确认Spring Boot应用的端口,把curl命令的端口改成正确的(比如默认8080):
curl -k -H "Content-Type: application/json" -X GET http://localhost:8080/v1/data/groceries - 修正Repository的HQL语句,改用实体类名和字段名
- 给Controller的
getAllGroceries()方法加上return语句 - 重启应用,重新测试
如果还是有问题,可以检查应用启动日志,看有没有Repository初始化的错误,这会直接导致端点无法正常注册。
内容的提问来源于stack exchange,提问作者smeeb

