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 这个上限的。