spring中的AntPathMatcher路徑匹配規則

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 這個上限的。


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章