AntPathMatcher.match
时间: 2023-06-22 15:24:01 浏览: 157
AntPathMatcher中的match方法用于比较两个路径是否匹配,其中一个路径可以包含Ant风格的通配符(如"?"和"*"),另一个路径则是待匹配的路径。它的方法签名如下:
```
public boolean match(String pattern, String path)
```
其中,pattern表示包含通配符的路径模式,path表示待匹配的路径。如果两个路径匹配,则返回true;否则返回false。
例如,下面的代码使用AntPathMatcher匹配一个URL路径是否匹配注册的API路径:
```
AntPathMatcher pathMatcher = new AntPathMatcher();
String apiPattern = "/api/users/*";
String requestPath = "/api/users/123";
if (pathMatcher.match(apiPattern, requestPath)) {
// 匹配成功,处理API请求
} else {
// 不匹配,忽略该请求
}
```
在上面的例子中,AntPathMatcher会将"/api/users/*"解析成一个路径模式,其中"*"表示一个或多个任意字符。如果请求路径"/api/users/123"与该模式匹配,则返回true,否则返回false。
相关问题
antpathmatcher.match
antpathmatcher.match是Ant路径匹配器的一个方法,用于在给定的模式和路径之间进行匹配。它支持Ant风格的通配符,如“*”和“?”。如果模式与路径匹配,则返回true,否则返回false。
antpathmatcher源码
AntPathMatcher是Spring框架中用于Ant风格路径匹配的工具类,其源码如下:
```java
public class AntPathMatcher implements PathMatcher, Serializable {
private static final long serialVersionUID = 1L;
public static final String DEFAULT_PATH_SEPARATOR = "/";
private static final int CACHE_TURNOFF_THRESHOLD = 65536;
private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?\\}");
private static final char[] WILDCARD_CHARS = { '*', '?', '{' };
private String pathSeparator;
private PathSeparatorPatternCache pathSeparatorPatternCache;
private boolean trimTokens = true;
private volatile Boolean cachePatterns;
private final Map<String, String[]> tokenizedPatternCache = new ConcurrentHashMap<>(256);
private final Map<String, AntPathStringMatcher> stringMatcherCache = new ConcurrentHashMap<>(256);
public AntPathMatcher() {
this.pathSeparator = DEFAULT_PATH_SEPARATOR;
this.pathSeparatorPatternCache = new PathSeparatorPatternCache(DEFAULT_PATH_SEPARATOR);
}
public AntPathMatcher(String pathSeparator) {
Assert.notNull(pathSeparator, "'pathSeparator' is required");
this.pathSeparator = pathSeparator;
this.pathSeparatorPatternCache = new PathSeparatorPatternCache(pathSeparator);
}
public void setPathSeparator(@Nullable String pathSeparator) {
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
this.pathSeparatorPatternCache = new PathSeparatorPatternCache(this.pathSeparator);
}
public void setTrimTokens(boolean trimTokens) {
this.trimTokens = trimTokens;
}
public void setCachePatterns(boolean cachePatterns) {
this.cachePatterns = cachePatterns;
}
public boolean isPattern(String path) {
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
}
public boolean match(String pattern, String path) {
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
}
String[] pattDirs = tokenizePath(pattern);
String[] pathDirs = tokenizePath(path);
int pattIdxStart = 0;
int pattIdxEnd = pattDirs.length - 1;
int pathIdxStart = 0;
int pathIdxEnd = pathDirs.length - 1;
// Match all elements up to the first **
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
String pattDir = pattDirs[pattIdxStart];
if ("**".equals(pattDir)) {
break;
}
if (!matchStrings(pattDir, pathDirs[pathIdxStart])) {
return false;
}
pattIdxStart++;
pathIdxStart++;
}
if (pathIdxStart > pathIdxEnd) {
// Path is exhausted, only match if rest of pattern is * or **'s
if (pattIdxStart > pattIdxEnd) {
return (pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) :
!path.endsWith(this.pathSeparator));
}
if (!this.trimTokens) {
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!"**".equals(pattDirs[i])) {
return false;
}
}
return true;
}
return (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") &&
path.endsWith(this.pathSeparator));
} else if (pattIdxStart > pattIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
} else if (!this.trimTokens && "**".equals(pattDirs[pattIdxStart])) {
// Path start definitely matches due to "**" part in pattern.
return true;
}
// up to last '**'
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
String pattDir = pattDirs[pattIdxEnd];
if (pattDir.equals("**")) {
break;
}
if (!matchStrings(pattDir, pathDirs[pathIdxEnd])) {
return false;
}
pattIdxEnd--;
pathIdxEnd--;
}
if (pathIdxStart > pathIdxEnd) {
// Path is exhausted
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!"**".equals(pattDirs[i])) {
return false;
}
}
return true;
}
while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
int patIdxTmp = -1;
for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
if (pattDirs[i].equals("**")) {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == pattIdxStart + 1) {
// '**/**' situation, so skip one
pattIdxStart++;
continue;
}
// Find the pattern between padIdxStart & padIdxTmp in str between
// strIdxStart & strIdxEnd
int patLength = (patIdxTmp - pattIdxStart - 1);
int strLength = (pathIdxEnd - pathIdxStart + 1);
int foundIdx = -1;
strLoop:
for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
String subPat = pattDirs[pattIdxStart + j + 1];
String subStr = pathDirs[pathIdxStart + i + j];
if (!matchStrings(subPat, subStr)) {
continue strLoop;
}
}
foundIdx = pathIdxStart + i;
break;
}
if (foundIdx == -1) {
return false;
}
pattIdxStart = patIdxTmp;
pathIdxStart = foundIdx + patLength;
}
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!"**".equals(pattDirs[i])) {
return false;
}
}
return true;
}
protected String[] tokenizePath(String path) {
String[] pathArr = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
if (this.cachePatterns == null || this.cachePatterns.booleanValue()) {
String key = path;
String[] tokenized = this.tokenizedPatternCache.get(key);
if (tokenized == null) {
tokenized = pathArr;
this.tokenizedPatternCache.put(key, tokenized);
}
return tokenized;
} else {
return pathArr;
}
}
protected boolean matchStrings(String pattern, String str) {
return getStringMatcher(pattern).matchStrings(str);
}
protected AntPathStringMatcher getStringMatcher(String pattern) {
AntPathStringMatcher matcher = this.stringMatcherCache.get(pattern);
if (matcher == null) {
matcher = new AntPathStringMatcher(pattern, this.caseSensitive);
this.stringMatcherCache.put(pattern, matcher);
}
return matcher;
}
private static class PathSeparatorPatternCache {
private final String endsOnWildCard;
private PathSeparatorPatternCache(String endsOnWildCard) {
this.endsOnWildCard = endsOnWildCard;
}
public String getEndsOnWildCard() {
return this.endsOnWildCard;
}
public String getReplacement() {
return (this.endsOnWildCard.equals("/") ? "\\/" : this.endsOnWildCard);
}
}
}
```
AntPathMatcher的主要实现方法是match和tokenizePath,其中match方法用于路径的匹配,tokenizePath方法用于将路径按照路径分隔符"/"分割成多个部分。
AntPathMatcher的match方法实现非常复杂,主要是将路径按照路径分隔符"/"分割成多个部分,然后逐个匹配每个部分,如果匹配的部分中含有通配符,则按照通配符的规则进行匹配,如果匹配成功,则返回true,否则返回false。
AntPathMatcher还提供了一些其他的内部方法,比如getStringMatcher方法用于获取AntPathStringMatcher对象,该对象用于匹配Ant风格的路径中的每个部分。
总之,AntPathMatcher是一个非常实用的工具类,可以方便地实现Ant风格路径的匹配和路径变量的解析,为Spring框架提供了很好的支持。
阅读全文