最近项目框架升级,发现原本支持url带有%20
这种编码后的空格,升级后却报404。
例如:有个Controller处理路径为/hello/world
的请求。
升级前(spring core 4.2.3.RELEASE)://hello/world
和/%20/hello/world
都能正常返回。
升级后(spring core 5.3.23)://hello/world
正常返回,但是/%20/hello/world
却报404。
我们知道Spring MVC是通过url查找匹配的handler来处理请求的。
通过DispatcherServlet#doDispatch方法层层跟进,我们能定位到org.springframework.util.AntPathMatcher是最终确定路径是否能匹配的地方。
那么,想要找出问题的原因所在,我们只需要对比升级前和升级后的版本AntPathMatcher有什么区别即可。
1
2
3
4
| // spring core 4.2.3.RELEASE
// pattern为controller的路径,path为url中的路径
String[] pattDirs = tokenizePattern(pattern); // /hello/world => [hello, world]
String[] pathDirs = tokenizePath(path); // /%20/hello/world => [hello, world]
|
1
2
3
4
5
6
7
8
9
10
| // spring core 5.3.23
String[] pattDirs = tokenizePattern(pattern);
// 这是新版特有的代码,就是这里直接返回false。
// 这里涉及到trimTokens变量,如果trimTokens为true,相同参数的情况下,升级前后的匹配结果就一致了
// 而且刚好5.3.23默认为false,4.2.3默认为true
if (fullMatch && this.caseSensitive && !isPotentialMatch(path, pattDirs)) {
return false;
}
String[] pathDirs = tokenizePath(path);
|
所以,只需要将doDispatch时使用的AntPathMatcher的trimTokens设置为true即可。
那么问题来了,怎么设置呢?
一种方法是,在代码里一层层找能设置AntPathMatcher的扩展点。另一种当然就是直接搜索引擎搜了。
然后我就搜到了这个,正好与我的需求相反。Disable trimming of whitespace from path variables in Spring 3.2。
解决方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| @Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setPathMatcher(antPathMatcher());
}
@Bean
public AntPathMatcher antPathMatcher() {
final AntPathMatcher antPathMatcher = new AntPathMatcher();
antPathMatcher.setTrimTokens(true); //此为重点
return antPathMatcher;
}
}
|