本文详解 Spring Boot 应用中因 server.servlet.context-path 与 @RequestMapping 重复配置引发的路径解析错误,重点说明如何修复 Failed to convert from type [String] to [Long] 这类典型 400 错误。
本文详解 spring boot 应用中因 `server.servlet.context-path` 与 `@requestmapping` 重复配置引发的路径解析错误,重点说明如何修复 `failed to convert from type [string] to [long]` 这类典型 400 错误。
在 Spring Boot 开发中,当控制器方法声明为 @GetMapping("/buscar/{name}"),而实际请求 URL 却使用查询参数形式(如 ?name=Pisicola)时,若路径匹配机制被意外干扰,极易触发底层 HandlerMapping 的误判——将路径片段(如 buscar)错误解析为 @PathVariable Long id 类型参数,从而抛出 For input string: "buscar" 的 NumberFormatException。
根本原因在于 双重上下文路径叠加:
你在 application.properties 中设置了全局上下文路径:
server.servlet.context-path=/api
同时又在控制器上重复声明:
@RestController
@RequestMapping("/api/heroes") // ❌ 冗余前缀!这导致完整访问路径变为 /api/api/heroes/...,而 Spring 在尝试匹配 @GetMapping("/buscar/{name}") 时,因路径不匹配,fallback 到默认的 REST repository 路由或隐式 ID 解析逻辑,最终将 buscar 当作 id 参数强制转为 Long,引发崩溃。
✅ 正确做法是 只保留一处上下文定义:
- 保持 application.properties 中的 server.servlet.context-path=/api;
- 将控制器 @RequestMapping 改为相对路径:
@RestController @RequestMapping("/heroes") // ✅ 去掉 "/api",仅保留业务路径 public class HeroController { // ... }
此时,你的搜索接口真实路径为:
GET http://localhost:8080/api/heroes/buscar?name=Pisicola
⚠️ 注意:这是 @RequestParam 模式,应使用 ?name=xxx,而非 /{name} 路径变量。因此还需同步修正方法签名:
@GetMapping("/buscar") // ✅ 使用查询参数,非路径变量
public ResponseEntity<List<Heroe>> findHeroByName(@RequestParam String name) {
List<Heroe> heroes = heroesRepository.findByName(name);
return ResponseEntity.ok(heroes); // 推荐使用静态工厂方法提升可读性
}? 验证技巧:启动应用后访问 http://localhost:8080/actuator/mappings(需启用 Actuator),查看实际注册的端点,确认 /api/heroes/buscar 是否正确映射。
此外,请检查 HeroesRepository 是否被 @RepositoryRestResource 意外暴露为 Spring Data REST 端点(它会自动注册 /api/heroes/search/findByName?name=xxx)。若无需 REST 自动导出,建议移除该注解,避免与自定义控制器冲突。
总结:
- ✅ server.servlet.context-path 是全局前缀,所有 @RequestMapping 应基于此“之后”书写;
- ✅ @RequestParam 对应 ?key=value,@PathVariable 对应 /value,二者不可混用;
- ✅ 使用 ResponseEntity.ok() / badRequest() 等静态方法替代 new ResponseEntity<>(..., HttpStatus.xxx),代码更简洁安全;
- ✅ 启用 Actuator 并检查 /mappings,是诊断路径问题最直接的手段。

















