SpringBoot中NoHandlerFoundException捕获的URL模式异常问题
问题原因
当自定义Controller路径前缀为loans时,Spring Data Rest的RepositoryRestHandlerMapping会优先匹配该路径——因为Spring Data Rest默认会将实体类名转为复数作为Repository的基础路径(比如存在Loan实体时,对应Repository的路径就是/loans)。
访问/loans/123A/something时,RepositoryRestHandlerMapping会把123A解析为Loan实体的ID,something解析为子资源,但由于不存在对应的子资源映射,最终抛出ResourceNotFoundException,而非NoHandlerFoundException(因为已有HandlerMapping匹配了请求)。
而前缀为loan时,Spring Data Rest没有对应的Repository路径,无HandlerMapping匹配请求,才会抛出NoHandlerFoundException并被你的ControllerAdvice捕获。
解决方案
方案1:修改Spring Data Rest基础路径,隔离路径冲突
在application.properties中配置Spring Data Rest的统一基础路径,使其与自定义Controller路径隔离:
spring.data.rest.base-path=/api
配置后,Spring Data Rest的所有接口都会以/api为前缀(比如/api/loans),不再和自定义的/loans路径冲突。
方案2:调整自定义Controller的路径前缀
直接修改自定义Controller的路径前缀,避开Spring Data Rest默认的实体复数路径,示例:
@GetMapping("/loan-service/{pathvariable}/somethings")
方案3:调整HandlerMapping优先级,让自定义Controller优先匹配
通过配置类将处理自定义Controller的RequestMappingHandlerMapping优先级设为高于RepositoryRestHandlerMapping:
@Configuration public class WebMvcPriorityConfig { @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; @PostConstruct public void configureHandlerMappingOrder() { // RepositoryRestHandlerMapping默认order为1,设为0让自定义Controller映射优先 requestMappingHandlerMapping.setOrder(0); } }
这样当请求路径同时匹配自定义Controller和Spring Data Rest的路径时,会优先使用自定义Controller的映射,未匹配时才会触发NoHandlerFoundException。
内容的提问来源于stack exchange,提问作者Manik_Vashisht

