最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Spring AntPathMatcher的doMatch方法

 更新時(shí)間:2021年09月08日 11:07:10   作者:王其狗勾兒癢  
這篇文章主要介紹了使用Spring AntPathMatcher的doMatch方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

AntPathMatcher的doMatch方法

AntPathMatcher.doMatch(...), 是解決模式匹配的源碼

有4個(gè)步驟

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

2. 第一個(gè)while 循環(huán), 用來(lái)判斷絕對(duì)匹配 /xxx/abc ==> /xxx/abc

3. 第二個(gè)while循環(huán)兩個(gè)字符串?dāng)?shù)組都從最后的下標(biāo)開(kāi)始匹配, 直到遇到pattDir為'**'時(shí)結(jié)束

4. 第三個(gè)while循環(huán), 主要解決有多個(gè)'**'字符串./**/djdjdjd/**, /a/**/**/b/**/c/**/*.class等

// 解決模式匹配的函數(shù), 返回true or false 表示是否匹配
// 參數(shù) pattern: 表示模式字符串
	    path: 文件的路徑
	protected boolean doMatch(String pattern, String path, boolean fullMatch, Map<String, String> 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的可分配下標(biāo) pattIdxStart ~ pattIdxEnd
		// path的可分配下標(biāo)	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. 第一個(gè)while 循環(huán), 用來(lái)判斷絕對(duì)匹配的   /xxx/abc ==> /xxx/abc
		// 兩個(gè)字符串都從下標(biāo)0開(kāi)始, 直到模式字符串遇到**結(jié)束
		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), 已經(jīng)逐一的匹配到了
		if (pathIdxStart > pathIdxEnd) {
			
			/*
			// Path is exhausted, only match if rest of pattern is * or **'s
			if (pattIdxStart > pattIdxEnd) {
				// 判斷最后一個(gè)字符是否為'/'
				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;
			}
			// 不會(huì)執(zhí)行到這里
			for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
				if (!pattDirs[i].equals("**")) {
					return false;
				}
			}
			*/
			// 這里返回true 一般是相等的字符串匹配(長(zhǎng)度相同)
			// /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. 兩個(gè)字符串?dāng)?shù)組都從最后的下標(biāo)開(kāi)始匹配, 直到遇到pattDir為'**'時(shí)結(jié)束
		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 
			// 即只有一個(gè)**, 而且**沒(méi)發(fā)揮到什么作用 
			// 測(cè)試
			// AntPathMatcher ant = new AntPathMatcher("/");
			//String pattern = "/abc/**/*.class";
			//String path = "/abc/ddd.class";
			//System.out.println(ant.match(pattern, path));
			return true;
		}
 
		// 4. 第3個(gè)while循環(huán), 主要解決有多個(gè)'**'字符串.	/**/djdjdjd/**, /a/**/**/b/**/c/**/*.class等
		// 每次下標(biāo)又從pattIdxStart+1開(kāi)始
		while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
			int patIdxTmp = -1;	// 這個(gè)用來(lái)指向**的位置
			for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
				if (pattDirs[i].equals("**")) {
					patIdxTmp = i;
					break;
				}
			}
			if (patIdxTmp == pattIdxStart + 1) {
				// '**/**' 遇到連續(xù)的/**/**就跳過(guò), 因?yàn)檫@沒(méi)有意義, 一個(gè)/**也可以表達(dá)多條路徑
				pattIdxStart++;
				continue;
			}
			// patLength: 兩個(gè)'**'之間的字符串的長(zhǎng)度  /**/a/b/** = 2
			// strLength: 路徑還剩多少個(gè)沒(méi)匹配 	/a/b/c/d	如果/a/b都匹配了, 就只剩下/b/c = 2
			int patLength = (patIdxTmp - pattIdxStart - 1);
			int strLength = (pathIdxEnd - pathIdxStart + 1);
			int foundIdx = -1;
 
			strLoop:
			// 因?yàn)橐呀?jīng)確定了有 /**/a/b/**這樣的模式字符串存在, 中間2長(zhǎng)度
			// 如果存在/q/a/b/c/d 有5個(gè)長(zhǎng)度, 那么就要循環(huán)3次
			// 第一次匹配 /a/b => /q/a
			// 第二次	 /a/b => /a/b	=> 這里已經(jīng)匹配到了, 所以就break了
			// 			 /a/b => /b/c
			// 			 /a/b => /c/d
			// 當(dāng)然, 如果存在更復(fù)雜的如: /**/a/b/**/a/b/**/a/b/**, 外層的while循環(huán)就會(huì)做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;
			}
		}
		//如果上面的都沒(méi)有返回值 /** => /sdjdd/djkd/.....就會(huì)在此處返回
        // 當(dāng)然還有更多的
		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();
// 可根據(jù)需求做動(dòng)態(tài)匹配
String pattern = "/app/*.html"
if (antPathMatcher.match(pattern, url)) {
   // 根據(jù)入?yún)rl和pattern匹配上返回ture,否則false.
     return true;
 }
   return false;
}

下面是模糊匹配規(guī)則

也就是在響應(yīng)的路徑上添加* 或則 ** 對(duì)路徑進(jìn)行替代即可。

URL路徑 說(shuō)明
/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 文件

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java接口返回參數(shù)按照請(qǐng)求參數(shù)進(jìn)行排序方式

    java接口返回參數(shù)按照請(qǐng)求參數(shù)進(jìn)行排序方式

    這篇文章主要介紹了java接口返回參數(shù)按照請(qǐng)求參數(shù)進(jìn)行排序方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java集合Collection實(shí)現(xiàn)類解析ArrayList?LinkedList及Vector

    java集合Collection實(shí)現(xiàn)類解析ArrayList?LinkedList及Vector

    這篇文章主要為大家介紹了java集合Collection實(shí)現(xiàn)類解析ArrayList?LinkedList及Vector,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 關(guān)于java自定義線程池的原理與實(shí)現(xiàn)

    關(guān)于java自定義線程池的原理與實(shí)現(xiàn)

    本文介紹了如何自定義線程池和阻塞隊(duì)列,包括阻塞隊(duì)列的實(shí)現(xiàn)方法,線程池的構(gòu)建以及拒絕策略的應(yīng)用,詳細(xì)闡述了線程池中任務(wù)的提交和執(zhí)行流程,以及如何處理任務(wù)超出隊(duì)列容量的情況
    2022-04-04
  • java短路邏輯運(yùn)算符實(shí)例用法詳解

    java短路邏輯運(yùn)算符實(shí)例用法詳解

    在本篇文章里小編給大家分享的是一篇關(guān)于java短路邏輯運(yùn)算符實(shí)例用法內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。
    2021-04-04
  • Java規(guī)則引擎Easy Rules的使用介紹

    Java規(guī)則引擎Easy Rules的使用介紹

    這篇文章主要介紹了Java規(guī)則引擎Easy Rules的使用介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • SpringBoot WebSocket實(shí)時(shí)監(jiān)控異常的詳細(xì)流程

    SpringBoot WebSocket實(shí)時(shí)監(jiān)控異常的詳細(xì)流程

    最近做了一個(gè)需求,消防的設(shè)備巡檢,如果巡檢發(fā)現(xiàn)異常,通過(guò)手機(jī)端提交,后臺(tái)的實(shí)時(shí)監(jiān)控頁(yè)面實(shí)時(shí)獲取到該設(shè)備的信息及位置,然后安排員工去處理。這篇文章主要介紹了SpringBoot WebSocket實(shí)時(shí)監(jiān)控異常的全過(guò)程,感興趣的朋友一起看看吧
    2021-10-10
  • Java Fork/Join框架

    Java Fork/Join框架

    Fork/Join框架是Java7中新增的一項(xiàng)特性,也是Java7平臺(tái)的其中一項(xiàng)主要改進(jìn)。下面我們就來(lái)簡(jiǎn)單探討下Java的Fork/Join框架
    2016-09-09
  • 解決Java調(diào)用BAT批處理不彈出cmd窗口的方法分析

    解決Java調(diào)用BAT批處理不彈出cmd窗口的方法分析

    本篇文章是對(duì)Java調(diào)用BAT批處理不彈出cmd窗口的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Spring-data-redis操作redis cluster的示例代碼

    Spring-data-redis操作redis cluster的示例代碼

    這篇文章主要介紹了Spring-data-redis操作redis cluster的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • Spring學(xué)習(xí)筆記之RestTemplate使用小結(jié)

    Spring學(xué)習(xí)筆記之RestTemplate使用小結(jié)

    這篇文章主要給大家介紹了關(guān)于Spring學(xué)習(xí)筆記之RestTemplate使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08

最新評(píng)論

蒲城县| 且末县| 景德镇市| 桑日县| 中山市| 甘孜县| 忻城县| 宜兰县| 北辰区| 肥乡县| 龙胜| 山阴县| 五莲县| 金川县| 连南| 松潘县| 渝北区| 东乡| 九龙城区| 台中市| 洞口县| 兴文县| 宁陵县| 长海县| 策勒县| 太康县| 闻喜县| 贞丰县| 克东县| 阳东县| 灵寿县| 合川市| 东乡族自治县| 富顺县| 遂昌县| 革吉县| 个旧市| 青岛市| 渝中区| 海原县| 舟山市|