AntPathMatcher源码实现* ** ?
时间: 2023-07-13 09:41:30 浏览: 40
AntPathMatcher的匹配算法主要分为两种情况:路径无通配符和路径带通配符。
当路径无通配符时,直接使用字符串比较即可。例如,路径字符串"/hello/world"可以和模式字符串"/hello/world"精确匹配。
当路径带通配符时,需要对模式字符串进行解析,然后逐一比较路径字符串的各个部分。AntPathMatcher支持两种通配符:"*"和"**"。
对于"*"通配符,匹配任意非路径分隔符字符。例如,模式字符串"/hello/*/world"可以匹配路径"/hello/foo/world"、"/hello/bar/world"等。
对于"**"通配符,匹配任意字符,包括路径分隔符。例如,模式字符串"/hello/**/world"可以匹配路径"/hello/foo/bar/world"、"/hello/world"等。
下面是AntPathMatcher的源码实现:
```java
public class AntPathMatcher {
private static final String DEFAULT_PATH_SEPARATOR = "/";
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
public void setPathSeparator(String pathSeparator) {
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
}
public boolean match(String pattern, String path) {
if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(path)) {
return false;
}
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
}
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, true, true);
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator, true, true);
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 (pattIdxStart == pattIdxEnd && "*".equals(pattDirs[pattIdxStart]) && path.endsWith(this.pathSeparator)) {
return true;
}
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!"**".equals(pattDirs[i])) {
return false;
}
}
return true;
} else if (pattIdxStart > pattIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
} else if (!pattern.contains("**")) {
// No more **'s. Check if rest of pattern matches.
return (pattIdxStart == pattIdxEnd && "*".equals(pattDirs[pattIdxStart]) && path.endsWith(this.pathSeparator)) ||
matchStrings(pattDirs, pattIdxStart, pattIdxEnd, pathDirs, pathIdxStart, pathIdxEnd);
}
// Pattern contains '**'
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 ("**".equals(pattDirs[i])) {
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;
}
private boolean matchStrings(String pattern, String str) {
return (pattern.equals(str) || pattern.equals("*"));
}
private boolean matchStrings(String[] pattDirs, int pattIdxStart, int pattIdxEnd,
String[] strDirs, int strIdxStart, int strIdxEnd) {
while (pattIdxStart <= pattIdxEnd && strIdxStart <= strIdxEnd) {
String pattDir = pattDirs[pattIdxStart];
String strDir = strDirs[strIdxStart];
if (!matchStrings(pattDir, strDir)) {
return false;
}
pattIdxStart++;
strIdxStart++;
}
return (pattIdxStart > pattIdxEnd && strIdxStart > strIdxEnd);
}
}
```
上面的代码中,match方法用于判断一个路径是否匹配一个模式;matchStrings方法用于判断两个字符串是否匹配。AntPathMatcher中的核心算法比较复杂,需要仔细阅读代码才能理解。