antPathMatcher用法:
使用通配符進行匹配
- ?匹配一個字符(matches one character)。
- * 匹配0個或者多個字符 ( matches zero or more characters)。
- ** 匹配url中的0個或多個子目錄 (matches zero or more directories in a path)
- {spring:[a-z]+} 匹配滿足正則表達式[a-z]+的路徑,這些路徑賦值給變量"spring" (matches the regexp
[a-z]+
as a path variable named "spring")
用例:
1. /erb/contract/?est.json 匹配/erb/contract/test.json、/erb/contract/aest.json、/erb/contract/best.json, 但不匹配/erb/contract/est.json ;
2. /erb/contract/*.json 匹配以.json的路徑,/erb/contract/a.json、/erb/contract/ab.json、/erb/contract/abcXXX.json
3. /erb/contract/* 匹配以 /erb/contract/開始的路徑,但只能是一級,/erb/contract/a、/erb/contract/abXXX、/erb/contract/a.json、/erb/contract/abXX.json、/erb/contract/a.do、/erb/contract/abXX.do 等
4. /**/contract/** ,只要路徑含有contract就可以匹配,比如:/erb/XXX/contract/a/b/XX、/erb/XXX/contract/a/b/XX.XX
5. /**/{contract:[a-z,A-Z]+}/**, 比如:/erb/XXX/contract/a/b/XX、/erb/XXX/contractXXX/a/b/XX.XX
long begin = System.currentTimeMillis();
AntPathMatcher antPathMatcher = new AntPathMatcher();
boolean match = antPathMatcher.match("/**/contract/digital/view/info*/**",
"/erb/contract/digital/view/info.json?signatureEncode=XXXXXXXXXX");
System.out.println(String.format("match:%s, 耗時:%d", match, (System.currentTimeMillis()-begin)));
boolean match1 = antPathMatcher.match("/erb/contract/?est.json", "/erb/contract/test.json");
System.out.println(String.format("match1:%s, ", match1));
long begin2 = System.currentTimeMillis();
boolean match2 = antPathMatcher.match("/**/contract/digital/view/info",
"/org/contract/digital/view/info");
System.out.println(String.format("match2:%s, 耗時:%d,", match2, (System.currentTimeMillis()-begin2)));
boolean match3 = antPathMatcher.match("/erb/contract/*.json", "/erb/contract/XXX.json");
System.out.println(String.format("match3:%s ", match3));
boolean match4 = antPathMatcher.match("/erb/contract/**", "/erb/contract/XXX.XX");
System.out.println(String.format("match4:%s ", match4));
boolean match5 = antPathMatcher.match("/**/contract/**", "/XXX/XXX/contract/XXX/XX.XX");
System.out.println(String.format("match5:%s ", match5));
boolean match6 = antPathMatcher.match("/**/{contract:[a-z,A-Z]+}/**", "/XXX/XXX/contractXXX/XXX/XX.XX");
System.out.println(String.format("match6:%s, 總耗時:%d", match6,(System.currentTimeMillis()-begin)));
測試結果:
match:true, 耗時:9
match1:true,
match2:true, 耗時:0,
match3:true
match4:true
match5:true
match6:true, 總耗時:12
AntPathMatcher提供了豐富的API,主要以match()和matchStart()爲主,這二者都是調用doMatch()保護方法,AntPathMatcher單次計算是比較耗時的,但antPathMatcher使用了兩個Map對象做了緩存,路徑緩存stringMatcherCache和分詞緩存tokenizedPatternCache,緩存初始大小爲256,最大爲65536;
tokenizedPatternCache用於存放正則規則和其對應的分詞,key:正則表達式,vlaue:是正則表達式分詞後的分詞String[] tokenized,正則規則默認以'/'進行分詞,分詞符默認是'/',分詞符可以通過pathSeparator自行指定。
stringMatcherCache待匹配路徑緩存,原理和緩存規則同tokenizedPatternCache,key:正則表達式分詞後的分詞,value:是其對應的AntPathStringMatcher對象,每個AntPathStringMatcher對應一個Pattern
注意下,這裏緩存有個問題:兩個cache的數量都不能超過65536,有其中任意一個cache超過這個限制,則會清空整個cache,並且會把緩存匹配標識Boolean cachePatterns置爲false;自此之後,規則分詞緩存和分詞對應的Matcher緩存 都會失效失效,每次都會重新分詞,重新創建內部類AntPathStringMatcher(其本質是個pattern),不知設計者是故意爲之,還是設計者沒有考慮到;但一般常規網站或系統的請求路徑很少能達到65536 這個上限的。