在spring中,当一个请求过来的时候会做路径匹配,下面我们就从源码层面分析一下路径匹配。
示例:
@RequestMapping(value = "/user/{aid}/online/**", method = RequestMethod.GET)
我们一起看看这个方法是如何寻找的,和一些相应的工具类
1、入口
我的项目使用的是自动配置的RequestMappingHandlerMapping类,在getHandlerInternal()方法中:
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
上面这行是根据你的请求path和request去查找合适的method了。在项目启动的时候,Spring就把路径和对应的方法加载到了内存中。进入上面方法:
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
可以看到如果根据lookupPath直接匹配上了,走第一个方法,如果没有,则需要根据规则匹配,走第二个方法。
mappingRegistry.getMappings().keySer()这个方法获取的类型为RequestMappingInfo类型,后面进入了RequestMappingInfo的getMatchingCondition()方法:
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
if (methods == null || params == null || headers == null || consumes == null || produces == null) {
return null;
}
PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) {
return null;
}
可以看到代码里面会查看各种条件是否匹配,包括,请求方法methods,参数params,请求头headers,还出入参类型等相关的consumers,produces等,最后一行就是我们要找的路径匹配patternsCondition.getMatchingCondition(request)。
这个方法会走到PatternRequestCondition的getMatchingPattern方法,然后调用如下方法,获取pattern:
if (this.pathMatcher.match(pattern, lookupPath)) {
return pattern;
}
上面这个pathMatcher的类型就是AntPathMatcher类,就是通过调用AntPathMatcher类的match方法,查看是否匹配,然后返回pattern。