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
— matchescom/test.jsp
but alsocom/tast.jsp
orcom/txst.jsp
com/*.jsp
— matches all.jsp
files in thecom
directorycom/**/test.jsp
— matches alltest.jsp
files underneath thecom
pathorg/springframework/**/*.jsp
— matches all.jsp
files underneath theorg/springframework
pathorg/**/servlet/bla.jsp
— matchesorg/springframework/servlet/bla.jsp
but alsoorg/springframework/testing/servlet/bla.jsp
andorg/servlet/bla.jsp
com/{filename:\\w+}.jsp
will matchcom/test.jsp
and assign the valuetest
to thefilename
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 1 | Pattern 2 | Result |
---|---|---|
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的第一个字符不是通配符,则认为不匹配