使用Spring AntPathMatcher的doMatch方法

网友投稿 1166 2022-12-10

使用Spring AntPathMatcher的doMatch方法

使用Spring AntPathMatcher的doMatch方法

目录AntPathMatcher的doMatch方法有4个步骤Spring的AntPathMatcher工具类用法AntPathMatcher下面是模糊匹配规则

AntPathMatcher的doMatch方法

AntPathMatcher.doMatch(...), 是解决模式匹配的源码

有4个步骤

1. 分解模式字符串, 分解路径字符串

2. 第一个while 循环, 用来判断绝对匹配 /xxx/abc ==> /xxx/abc

3. 第二个while循环两个字符串数组都从最后的下标开始匹配, 直到遇到pattDir为'**'时结束

4. 第三个while循环, 主要解决有多个'**'字符串./**/djdjdjd/**, /a/**/**/b/**/c/**/*.class等

// 解决模式匹配的函数, 返回true or false 表示是否匹配

// 参数 pattern: 表示模式字符串

path: 文件的路径

protected boolean doMatch(String pattern, String path, boolean fullMatch, Map uriTemplateVariables) {

if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {

return false;

}

1.1. 分解模式字符串

String[] pattDirs = tokenizePattern(pattern);

if (fullMatch && this.caseSensitive && !isPotentialMatch(path, pattDirs)) {

return false;

}

1.2 分解路径字符串

String[] pathDirs = tokenizePath(path);

// pattern的可分配下标 pattIdxStart ~ pattIdxEnd

// path的可分配下标 pathIdxStart ~ pathIdxEnd

int pattIdxStart = 0;

int pattIdxEnd = pattDirs.length - 1;

int pathIdxStart = 0;

int pathIdxEnd = pathDirs.length - 1;

// Match all elements up to the first **

// 2. 第一个while 循环, 用来判断绝对匹配的 /xxx/abc ==> /xxx/abc

// 两个字符串都从下标0开始, 直到模式字符串遇到**结束

while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {

String pattDir = pattDirs[pattIdxStart];

if ("**".equals(pattDir)) {

break;

}

if (!matchStrings(pattDir, pathDirs[pathIdxStart], uriTemplateVariables)) {

return false;

}

pattIdxStart++;

pathIdxStart++;

}

// pathIdxStart > pathIdEnd, 表示文件路径(path), 已经逐一的匹配到了

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));

}

if (!fullMatch) {

return true;

}

if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && path.endsWith(this.pathSeparator)) {

return true;

}

// 不会执行到这里

for (int i = pattIdxStart; i <= pattIdxEnd; i++) {

if (!pattDirs[i].equals("**")) {

return false;

}

}

*/

// 这里返回true 一般是相等的字符串匹配(长度相同)

// /abc/zzzz ==> /abc/zzzz

return true;

}

/*

else if (pattIdxStart > pattIdxEnd) {

// String not exhausted, but pattern is. Failure.

return false;

}

else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {

// Path start definitely matches due to "**" part in pattern.

return true;

}*/

// 3. 两个字符串数组都从最后的下标开始匹配, 直到遇到pattDir为'**'时结束

while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {

String pattDir = pattDirs[pattIdxEnd];

if (pattDir.equals("**")) {

break;

}

if (!matchStrings(pattDir, pathDirs[pathIdxEnd], uriTemplateVariables)) {

return false;

}

pattIdxEnd--;

pathIdxEnd--;

}

if (pathIdxStart > pathIdxEnd) {

for (int i = pattIdxStart; i <= pattIdxEnd; i++) {

if (!pattDirs[i].equals("**")) {

return false;

}

}

// 这里返回true 一般字符串为

// /xxxx/abcd/**/*.class => /xxxx/abcd /xxx.class

// 即只有一个**, 而且**没发挥到什么作用

// 测试

// AntPathMatcher ant = new AntPathMatcher("/");

//String pattern = "/abc/**/*.class";

//String path = "/abc/ddd.class";

//System.out.println(ant.match(pattern, path));

return true;

}

// 4. 第3个while循环, 主要解决有多个'**'字符串. /**/djdjdjd/**, /a/**/**/b/**/c/**/*.class等

// 每次下标又从pattIdxStart+1开始

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) {

// '**/**' 遇到连续的/**/**就跳过, 因为这没有意义, 一个/**也可以表达多条路径

pattIdxStart++;

continue;

}

// patLength: 两个'**'之间的字符串的长度 /**/a/b/** = 2

// strLength: 路径还剩多少个没匹配 /a/b/c/d 如果/a/b都匹配了, 就只剩下/b/c = 2

int patLength = (patIdxTmp - pattIdxStart - 1);

int strLength = (pathIdxEnd - pathIdxStart + 1);

int foundIdx = -1;

strLoop:

// 因为已经确定了有 /**/a/b/**这样的模式字符串存在, 中间2长度

// 如果存在/q/a/b/c/d 有5个长度, 那么就要循环3次

// 第一次匹配 /a/b => /q/a

// 第二次 /a/b => /a/b => 这里已经匹配到了, 所以就break了

// /a/b => /b/c

// /a/b => /c/d

// 当然, 如果存在更复杂的如: /**/a/b/**/a/b/**/a/b/**, 外层的while循环就会做3次判断,

//String pattern = "/**/a/b/**/a/b/**/a/b/**";

//String path = "/q/q/q/a/b/q/q/q/a/b/q/q/q/a/b/q/q/q/a/b";

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, uriTemplateVariables)) {

continue strLoop;

}

}

foundIdx = pathIdxStart + i;

break;

}

if (foundIdx == -1) {

return false;

}

pattIdxStart = patIdxTmp;

pathIdxStart = foundIdx + patLength;

}

for (int i = pattIdxStart; i <= pattIdxEnd; i++) {

if (!pattDirs[i].equals("**")) {

return false;

}

}

//如果上面的都没有返回值 /** => /sdjdd/djkd/.....就会在此处返回

// 当然还有更多的

return true;

}

Spring的AntPathMatcher工具类用法

AntPathMatcher

是org.springframework.util工具包下的方法。

/**

* A convenient, alternative constructor to use with a custom path separator.

* @param pathSeparator the path separator to use, must not be {@code null}.

* @since 4.1

*/

public AntPathMatcher(String pathSeparator) {

Assert.notNull(pathSeparator, "'pathSeparator' is required");

this.pathSeparator = pathSeparator;

this.pathSeparatorPatternCache = new PathSeparatorPatternCache(pathSeparator);

}

public boolean hasUrl(String url) {

if (url == null || "".equals(url)) {

return false;

}

AntPathMatcher antPathMatcher = new AntPathMatcher();

// 可根据需求做动态匹配

String pattern = "/app/*.html"

if (antPathMatcher.match(pattern, url)) {

// 根据入参url和pattern匹配上返回ture,否则false.

return true;

}

return false;

}

下面是模糊匹配规则

也就是在响应的路径上添加* 或则 ** 对路径进行替代即可。

URL路径

说明

/app/*.x

匹配(Matches)所有在app路径下的.x文件

/app/p?ttern

匹配(Matches) /app/pattern 和 /app/pXttern,但是不包括/app/pttern

/**/example

匹配(Matches) /app/example, /app/foo/example, 和 /example

/app/**/dir/file.

匹配(Matches) /app/dir/file.jsp, /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf, 和 /app/dir/file.java

/**/*.jsp

匹配(Matches)任何的.jsp 文件

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Android中PreferenceActivity使用详解
下一篇:SpringMVC路径匹配中使用通配符问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~