antpathmatcher遇到* ** ?是如何处理的
时间: 2023-07-23 11:56:31 浏览: 73
antpathmatcher是Spring Framework中的一个路径匹配工具类,用于实现Ant风格的路径匹配。
当遇到*时,antpathmatcher会匹配任意数量的字符(除了路径分隔符),例如:
- /user/*/info 可以匹配 /user/123/info、/user/abc/info等路径。
- /user/* 可以匹配 /user/123、/user/abc/info等路径。
当遇到**时,antpathmatcher会匹配任意数量的字符(包括路径分隔符),例如:
- /user/** 可以匹配 /user/123、/user/abc/info、/user/abc/def/ghi等路径。
当遇到?时,antpathmatcher会匹配一个字符(除了路径分隔符),例如:
- /user/?/info 可以匹配 /user/1/info、/user/a/info等路径。
总之,antpathmatcher可以通过*、**、?等通配符来实现灵活的路径匹配。
相关问题
antpathmatcher遇到* ** ?源码是如何处理的
antpathmatcher中对于*、**、?的处理可以在`org.springframework.util.AntPathMatcher`类中找到。
对于*的处理,可以看到在match方法中使用了一个while循环来一直匹配非路径分隔符的字符,直到遇到下一个路径分隔符或者字符串结束,代码如下:
```
while (pathIndex < pathLen && patternIndex < patternLen) {
char pattChar = pattern.charAt(patternIndex);
if (pattChar == '*') {
break;
}
...
}
```
对于**的处理,可以看到在match方法中使用了一个if-else语句来判断是否遇到了**,如果遇到了,则使用一个递归的方法来处理后面的路径部分。代码如下:
```
if (patternIndex == patternLen) {
return (pathIndex == pathLen);
}
else if ("**".equals(subPattern)) {
if (patternIndex == patternLen - 2) {
return true;
}
for (int i = pathIndex; i < pathLen; i++) {
if (match(patternIndex + 2, i, path, pathIndex, context)) {
return true;
}
}
return false;
}
else {
...
}
```
对于?的处理,可以看到在doMatch方法中直接判断字符是否相等即可,代码如下:
```
else if (patternChar == '?') {
// '?' 表示匹配任意单个字符
pathIndex++;
patternIndex++;
}
```
总之,antpathmatcher中对于*、**、?的处理都是通过特定的逻辑来实现的,从而实现了灵活的匹配功能。
antpathmatcher遇到* ** ?源码详细实现
antpathmatcher 是 Spring 框架中一个用于处理路径匹配的工具类,其主要功能是将一个给定的字符串与一个指定的模式进行匹配。在模式中,用户可以使用一些特殊的字符,比如 ? 和 *,来表示匹配任意字符和任意路径段。
在 antpathmatcher 中,* 和 ** 的含义如下:
- * 匹配任意字符(除了路径分隔符 /);
- ** 匹配任意路径段,可以是空路径段。
下面是 antpathmatcher 中关于 * 和 ** 的匹配实现:
```java
public boolean match(String pattern, String path) {
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
}
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, 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 there was no ** pattern, and the path is shorter or longer than the pattern, return false
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.endsWith(pattDirs[pattIdxEnd], this.allPattern)) {
return false;
}
return (pattIdxStart == pattIdxEnd && path.endsWith(this.pathSeparator)) || matchStrings(pattDirs, pattIdxStart, pattIdxEnd, pathDirs, pathIdxStart - 1);
}
else if (pattIdxStart > pattIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
}
else if (!this.ignoreAll(pattDirs, pattIdxStart, pattIdxEnd)) {
return false;
}
// Pattern contains **, full match guaranteed
if ("**".equals(pattDirs[pattIdxStart]) || "**".equals(pattDirs[pattIdxEnd])) {
return true;
}
// Match pattern to end in the path
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
String pattDir = pattDirs[pattIdxEnd];
if ("**".equals(pattDir)) {
break;
}
if (!matchStrings(pattDir, pathDirs[pathIdxEnd])) {
return false;
}
pattIdxEnd--;
pathIdxEnd--;
}
return (pathIdxStart > pathIdxEnd) || matchStrings(pattDirs, pattIdxStart, pattIdxEnd, pathDirs, pathIdxStart);
}
private boolean matchStrings(String pattern, String str) {
return this.stringMatcher.match(pattern, str);
}
private boolean matchStrings(String[] pattDirs, int pattStart, int pattEnd, String[] strDirs, int strStart) {
int patIdxStart = pattStart;
int patIdxEnd = pattEnd;
int strIdxStart = strStart;
int strIdxEnd = strDirs.length - 1;
while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
String patDir = pattDirs[patIdxEnd];
if ("**".equals(patDir)) {
break;
}
if (!matchStrings(patDir, strDirs[strIdxEnd])) {
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if (strIdxStart > strIdxEnd) {
// String is exhausted
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (!this.ignore(pattDirs[i])) {
return false;
}
}
return true;
}
else {
if (patIdxStart > patIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
}
}
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (this.allPattern.equals(pattDirs[i])) {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == patIdxStart + 1) {
// '**/**' situation, so skip one
patIdxStart++;
continue;
}
// Find the next pattern part in pattern
int patLength = (patIdxTmp - patIdxStart - 1);
int strLength = (strIdxEnd - strIdxStart + 1);
int foundIdx = -1;
strLoop:
for (int i = strIdxStart; i <= strIdxEnd - patLength; i++) {
for (int j = 0; j < patLength; j++) {
String subPat = (j + patIdxStart + 1 < patIdxTmp ? pattDirs[j + patIdxStart + 1] : null);
String subStr = strDirs[i + j];
if (!matchStrings(subPat, subStr)) {
continue strLoop;
}
}
foundIdx = i;
break;
}
if (foundIdx == -1) {
return false;
}
patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (!this.ignore(pattDirs[i])) {
return false;
}
}
return true;
}
```
在这段代码中,我们可以看到 antpathmatcher 的匹配实现是基于递归的。它将模式和路径都分解成一个个的路径段,然后在逐个匹配这些路径段。如果遇到 *,则匹配任意一个非路径分隔符的字符,如果遇到 **,则匹配任意的路径段,包括空路径段。
具体来说,这段代码实现了以下几个步骤:
1. 根据路径分隔符将模式和路径分解成一个个的路径段;
2. 逐个匹配模式和路径的路径段;
3. 如果遇到 **,则跳过中间的路径段,直接匹配后面的路径段;
4. 如果模式匹配成功,则返回 true,否则返回 false。
总的来说,antpathmatcher 的匹配实现相对较为复杂,但是能够处理各种情况下的路径匹配问题,而且在 Spring 框架中得到了广泛的应用。
阅读全文