最近项目升级了Spring的版本,遇到了个小坑,发现过去有一些运行正常的请求在升级Spring后变成404
先上结论,结论很简单,在Spring-webmvc-4.3.16及5.1.6中,可以用如下形式处理所有其他controller不匹配的GET请求
但在5.2.3中,不再支持,必须要写上@RequestMapping("/**")才可以成功匹配
下面是对spring匹配请求的源码分析
Spring中使用RequestMappingHandlerMapping处理请求的匹配逻辑,相关实际逻辑在父类AbstractHandlerMethodMapping中的,代码如下
当直接匹配失败后,会进入第一个红色框内模糊匹配逻辑,调用堆栈如下
AbstractHandlerMethodMapping.addMatchingMappings ->
RequestMappingInfoHandlerMapping.getMatchingMapping ->
RequestMappingInfo.getMatchingCondition
不用版本之间处理逻辑基本相同,这里注意当patterns(当前遍历到的项目中controller的url)为空集合时是认为匹配成功,而会继续往下执行的。
这里发现不同点在于patterns的初始化逻辑,下面是PatternsRequestCondition的初始化逻辑
下面是spring-web-mvc-4.3.16中对patterns的初始化逻辑,可以看到当传入的patterns为空集合时,返回的也会是空集合,上面提到空的集合是会被默认当做匹配所有请求
下面是spring-web-mvc-5.1.6中对patterns的初始化逻辑,逻辑有稍微的调整,但同样传入空集合返回的也是空集合
而在spring-web-mvc-5.2.3中可以看到当传入集合为空,将返回一个有一个元素""的集合,将会导致在模糊匹配时不会跳过而是进入匹配规则逻辑,故匹配默认controller失败
另外匹配结束后,在上面AbstractHandlerMethodMapping的第二个红框内还会做二次校验,当patterns不为空集合时会进行参数提取,由于url不匹配也将会导致报错