Spring工具类AntPathMatcher [1]
AntPathMatcher的继承层次关系
这个类实现PathMatcher
这个接口.
PathMatcher接口方法定义
boolean isPattern(string path)
: 用来检查给定的**path(pattern–匹配规则)**是否是个合法的匹配规则.boolean match(string pattern, string path)
:依据pattern的匹配策略来匹配path是否符合规则.boolean matchStart(String pattern, String path)
:确定该模式是否至少与给定的基本路径匹配String extractPathWithinPattern(String pattern, String path)
:剥离匹配模式的前导静态部分,只返回动态部分匹配的path.例如:
pattern = "myroot/*.html" ; path = "myroot/myfile.html"
会返回myfile.html
Map<String, String> extractUriTemplateVariables(String pattern, String path)
:匹配URI,并返回URI参数map;例如:
pattern = "/hotels/{hotel}" path = "/hotels/1"
那么返回的map包含hotel->1Comparator<String> getPatternComparator(String path)
:根据完整路径,返回一个适配匹配模式匹配路径排序的比较器String combine(String pattern1, String pattern2)
: 整合两个模式,合并成1个新模式并返回
AntPathMatcher实现接口方法细节
isPattern
@Override
public boolean isPattern(String path) {
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
}
包含*
或者?
就代表这个path是个匹配模式
match
首先看一下这个方法的调用时序图
默认分隔符是/
,首先 path 如果以分隔符开始 那么pattern必须也以分隔符开始,否则返回false
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
}
使用分隔符把pattern分隔成string数组,观察下面代码使用了ConcurrentHashMap作为缓存分隔好的模式提升性能.
protected String[] tokenizePattern(String pattern) {
String[] tokenized = null;
Boolean cachePatterns = this.cachePatterns;
if (cachePatterns == null || cachePatterns.booleanValue()) {
tokenized = this.tokenizedPatternCache.get(pattern);
}
if (tokenized == null) {
tokenized = tokenizePath(pattern);
//当缓存大于65536这个阈值的时候讲不再缓存,并且清理缓存
if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {
deactivatePatternCache();
return tokenized;
}
if (cachePatterns == null || cachePatterns.booleanValue()) {
this.tokenizedPatternCache.put(pattern, tokenized);
}
}
return tokenized;
}
如果是全路径并且区分大小写,那么就检查path是否有潜在匹配的可能,如果没有,返回不匹配,反之亦然
if (fullMatch && this.caseSensitive && !isPotentialMatch(path, pattDirs)) {
return false;
}
isPotentialMatch 源代码
private boolean isPotentialMatch(String path, String[] pattDirs)