PathMatcher、AntPathMatcher

PathMatcher

顶层接口,路径匹配的策略接口

用于org.springframework.core.io.support.PathMatchingResourcePatternResolver、org.springframework.web.servlet.handler.AbstractUrlHandlerMapping、org.springframework.web.servlet.mvc.WebContentInterceptor

 

boolean isPattern(String path);

boolean match(String pattern, String path);

boolean matchStart(String pattern, String path);

String extractPathWithinPattern(String pattern, String path);

Map<String, String> extractUriTemplateVariables(String pattern, String path);

Comparator<String> getPatternComparator(String path);

String combine(String pattern1, String pattern2);

 

 

AntPathMatcher

PathMatcher的ant实现

? 匹配一个字符

* 匹配0-N个字符

**匹配0-N个且包含目录分隔符/在内

{spring:[a-z]+}匹配正则 [a-z]+ 并且赋值给变量"spring"

 

官方举例

  • com/t?st.jsp — matches com/test.jsp but also com/tast.jsp or com/txst.jsp
  • com/*.jsp — matches all .jsp files in the com directory
  • com/**/test.jsp — matches all test.jsp files underneath the com path
  • org/springframework/**/*.jsp — matches all .jsp files underneath the org/springframework path
  • org/**/servlet/bla.jsp — matches org/springframework/servlet/bla.jsp but also org/springframework/testing/servlet/bla.jsp and org/servlet/bla.jsp
  • com/{filename:\\w+}.jsp will match com/test.jsp and assign the value test to the filename variable

 

常量 Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?}");  匹配 \{非贪婪1-N个非/字符} 如\{name}

 

#boolean isPattern(@Nullable String path)  path中任意包含 ? 、 * 、  同时有{和} ,则返回true

#boolean match(String pattern, String path)  执行doMatch的fullMatch

#boolean matchStart(String pattern, String path)   执行doMatch的非fullMatch

#String extractPathWithinPattern(String pattern, String path)  目的得出path在pattern中的映射

官方例子

  • '/docs/cvs/commit.html' and '/docs/cvs/commit.html -> ''
  • '/docs/*' and '/docs/cvs/commit -> 'cvs/commit'
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html -> 'commit.html'
  • '/docs/**' and '/docs/cvs/commit -> 'cvs/commit'
  • '/docs/**\/*.html' and '/docs/cvs/commit.html -> 'cvs/commit.html'
  • '/*.html' and '/docs/cvs/commit.html -> 'docs/cvs/commit.html'
  • '*.html' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • '*' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'

 

#Map<String, String> extractUriTemplateVariables(String pattern, String path)  提取pattern中的变量名和path中对应的变量值

例如 /hotels/{hotel} -> /hotels/1 得到hotel=1,/h?tels/{hotel} -> /hotels/1得到hotel=1,/hotels/{hotel}/bookings/{booking} -> /hotels/1/bookings/2得到hotel=1,booking=2

#Comparator<String> getPatternComparator(String path)  获取一个用于排序pattern的Comparator,内部实现是内部类AntPatternComparator,入参path的作用是判断当pattern1和pattern2都是常量时,谁是eq path的排前

AntPatternComparator的总体规则是pattern越明确、越短的排前面

#String combine(String pattern1, String pattern2)  合并2个pattern

官方例子

Pattern 1Pattern 2Result
null null  
/hotels null /hotels
null /hotels /hotels
/hotels /bookings /hotels/bookings
/hotels bookings /hotels/bookings
/hotels/* /bookings /hotels/bookings
/hotels/** /bookings /hotels/**/bookings
/hotels {hotel} /hotels/{hotel}
/hotels/* {hotel} /hotels/{hotel}
/hotels/** {hotel} /hotels/**/{hotel}
/*.html /hotels.html /hotels.html
/*.html /hotels /hotels.html
/*.html /*.txt IllegalArgumentException

 

#protected boolean doMatch(String pattern, @Nullable String path, boolean fullMatch,@Nullable Map<String, String> uriTemplateVariables)

核心匹配规则:

 对pattern进行tokenizePattern处理得到String[] pattDirs,若要求fullMatch&&大小写敏感,则执行isPotentialMatch,结果是false则认为不匹配;

对path进行tokenizePath处理得到String[] pathDirs, 对pathDirs和pattDirs的每个相同索引位置进行匹配

...

 

#protected String[] tokenizePattern(String pattern)   目的对pattern使用tokenizePath分割。先从缓存中获取(缓存默认开启,最多65536个),缓存未命中再使用tokenizePath获得结果,若缓存达到了65536阈值,则清空缓存并关闭缓存(估计是因为spring认为此时业务场景已不适用缓存),否则设置缓存

#protected String[] tokenizePath(String path) 使用StringUtils.tokenizeToStringArray对path按 pathSeparator(路径分割符 ,默认/)进行分割,并忽略分割后是 空字符串 的结果

#private boolean isPotentialMatch(String path, String[] pattDirs)  将path和pattDirs进行位差匹配。若trimTokens是false(默认false),直接认为是匹配;遍历pattDirs,对path进行每一个path分隔符(pathSeparator)的skip和pattDir的skip,若每次skip pattDir返回的长度小于pattDir的长度,且skipped不大于0或pattDir的第一个字符不是通配符,则认为不匹配

 

posted on 2021-10-07 16:26  icodegarden  阅读(873)  评论(0编辑  收藏  举报