欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的路徑匹配器AntPathMatcher詳解

 更新時(shí)間:2023年09月25日 10:01:58   作者:騎個(gè)小蝸牛  
這篇文章主要介紹了Spring中的路徑匹配器AntPathMatcher詳解,Spring的PathMatcher路徑匹配器接口,用于支持帶通配符的資源路徑匹配,本文提供了部分實(shí)現(xiàn)代碼,需要的朋友可以參考下

PathMatcher接口

Spring的PathMatcher路徑匹配器接口,用于支持帶通配符的資源路徑匹配。

使用場(chǎng)景

PathMatcher接口在Spring的許多場(chǎng)景下使用,比如:

  • PathMatchingResourcePatternResolver:資源掃描,啟動(dòng)時(shí)掃描并加載資源
  • AbstractUrlHandlerMapping:請(qǐng)求路徑映射到 Controller
  • WebContentInterceptor:攔截器攔截路徑分析

接口方法

方法描述
boolean isPattern(String path)判斷路徑是否是模式
boolean match(String pattern, String path)判斷路徑是否完全匹配
boolean matchStart(String pattern, String path)判斷路徑是否前綴匹配
前綴匹配的意思:路徑能與模式的前面部分匹配,但模式可能還有后面多余部分
例如:/test能前綴匹配/test/{id}(但模式還有多余的/{id}部分未匹配)
String extractPathWithinPattern(String pattern, String path)得到模式匹配的部分值
該方法只返回路徑的實(shí)際模式匹配部分
例如:myroot/*.html 匹配 myroot/myfile.html 路徑,結(jié)果為 myfile.html
Map<String, String> extractUriTemplateVariables(String pattern, String path)提取路徑中的路徑參數(shù)值
Comparator<String> getPatternComparator(String path)得到一個(gè)排序比較器,用于對(duì)匹配到的所有路徑進(jìn)行排序
String combine(String pattern1, String pattern2)合并兩個(gè)模式

AntPathMatcher類(lèi)

AntPathMatcher是Spring為PathMatcher接口提供的默認(rèn)實(shí)現(xiàn),支持Ant風(fēng)格的路徑匹配。

匹配規(guī)則

AntPathMatcher支持的匹配規(guī)則:

規(guī)則描述
?匹配一個(gè)字符
*在一個(gè)路徑段中匹配零個(gè)、一個(gè)或多個(gè)字符
**匹配零個(gè)或多個(gè)路徑段,直到路徑結(jié)束
{id}匹配一個(gè)路徑段,并將該路徑段的值作為變量id的變量值
{id:[a-z]+}匹配一個(gè)滿足正則([a-z]+)路徑段,并將該路徑段的值作為變量id的變量值

舉例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        // ?
        System.out.println(matcher.match("/test/a?c", "/test/abc"));// true
        // *
        System.out.println(matcher.match("/test/*", "/test/"));// true
        System.out.println(matcher.match("/test/*", "/test/aa"));// true
        System.out.println(matcher.match("/test/*.html", "/test/aa"));// false
        // **
        System.out.println(matcher.match("/test/**", "/test/"));// true
        System.out.println(matcher.match("/test/**", "/test/aa"));// true
        System.out.println(matcher.match("/test/**", "/test/aa/bb"));// true
        // {id}
        System.out.println(matcher.match("/test/{id}", "/test/111"));// true
        System.out.println(matcher.match("/test/a{id}", "/test/a111"));// true
        System.out.println(matcher.match("/test/{id}/aa", "/test/111/aa"));// true
        System.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-haha/aa"));// true
        // {id:[a-z]+}
        System.out.println(matcher.match("/test/{id:[a-z]+}", "/test/111"));// false
        System.out.println(matcher.match("/test/{id:[a-z]+}", "/test/abc"));// true
        System.out.println(matcher.match("/test/{id:\\w+}", "/test/1a_"));// true
        System.out.println(matcher.match("/test/{id:\\w+}", "/test/--"));// false
    }

一些不匹配情況原因:

模式路徑原因
/user/aaa//user/aaa結(jié)束符不一致
/user/*//user/aaa結(jié)束符不一致

實(shí)際在Spring項(xiàng)目中使用的時(shí)候,你會(huì)發(fā)現(xiàn):就算實(shí)際請(qǐng)求的結(jié)束符為 / ,但還是能匹配成功。這又是為什么呢?

兩個(gè)關(guān)鍵屬性:

  • useSuffixPatternMatch:設(shè)置是否使用后綴模式匹配,如“/user”是否匹配/user.*,默認(rèn)是這種模式下,實(shí)際請(qǐng)求.后面加任何后綴,都會(huì)匹配到。如:實(shí)際請(qǐng)求“/user.html”能匹配上“/user”。
  • useTrailingSlashMatch:設(shè)置是否使用后綴路徑模式匹配,如“/user”是否匹配“/user/”,默認(rèn)是這種模式下,實(shí)際請(qǐng)求加、后綴,都會(huì)匹配到。如:實(shí)際請(qǐng)求“/user/”能匹配上“/user”。

關(guān)鍵源碼:

PatternsRequestCondition類(lèi)的getMatchingPattern方法

private String getMatchingPattern(String pattern, String lookupPath) {
		// 模式與路徑相等,直接返回模式
		if (pattern.equals(lookupPath)) {
			return pattern;
		}
		// 如果使用后綴模式匹配,返回的模式會(huì)拼接上合適的后綴,如.html
		if (this.useSuffixPatternMatch) {
			if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) {
				for (String extension : this.fileExtensions) {
					if (this.pathMatcher.match(pattern + extension, lookupPath)) {
						return pattern + extension;
					}
				}
			}
			else {
				boolean hasSuffix = pattern.indexOf('.') != -1;
				if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {
					return pattern + ".*";
				}
			}
		}
		if (this.pathMatcher.match(pattern, lookupPath)) {
			return pattern;
		}
		// 如果使用后綴路徑模式匹配,返回的模式會(huì)拼接上/
		if (this.useTrailingSlashMatch) {
			if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {
				return pattern + "/";
			}
		}
		return null;
	}

因此,getMatchingPattern方法返回的模式再與請(qǐng)求路徑進(jìn)行模式匹配當(dāng)然能匹配上了。

主要方法

1. isPattern

判斷路徑是否是模式。

只要路徑中擁有 * 、 ? 、 {} ,則就是模式。

public boolean isPattern(@Nullable String path) {
    if (path == null) {
        return false;
    }
    boolean uriVar = false;
    for (int i = 0; i < path.length(); i++) {
        char c = path.charAt(i);
        if (c == '*' || c == '?') {
            return true;
        }
        if (c == '{') {
            uriVar = true;
            continue;
        }
        if (c == '}' && uriVar) {
            return true;
        }
    }
    return false;
}

示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.isPattern("/test/{id}"));// true
    }

2. match

判斷路徑是否完全匹配

public boolean match(String pattern, String path) {
    return doMatch(pattern, path, true, null);
}

示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.match("/test/*", "/test/111"));// true
        System.out.println(matcher.match("/test/**", "/test/111/222"));// true
        System.out.println(matcher.match("/test/{id}", "/test/111"));// true
        System.out.println(matcher.match("/test/{id}/aa", "/test/111/aa"));// true
        System.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-haha/aa"));// true
        System.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-/aa"));// true
    }

3. matchStart

判斷路徑是否前綴匹配

前綴匹配的意思:路徑能與模式的前面部分匹配,但模式可能還有后面多余部分(可以理解為模式是否是以路徑開(kāi)頭)

public boolean matchStart(String pattern, String path) {
    return doMatch(pattern, path, false, null);
}

示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.matchStart("/test/*", "/test"));// true
        System.out.println(matcher.matchStart("/test/aa/*", "/test"));// true
        System.out.println(matcher.matchStart("/test/{id}", "/test"));// true
        System.out.println(matcher.matchStart("/test/{id}-{name}/aa", "/test"));// true
        System.out.println(matcher.matchStart("/test/{id}", "/test/111/222"));// false
    }

4. extractPathWithinPattern

得到模式匹配的映射部分。找出通過(guò)*或者?匹配上的那一段路徑及其后續(xù)路徑。

示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.extractPathWithinPattern("/test/*", "/test"));//
        System.out.println(matcher.extractPathWithinPattern("/test/*", "/test/aa"));// aa
        System.out.println(matcher.extractPathWithinPattern("/test/**", "/test/aa/bb"));// aa/bb
        System.out.println(matcher.extractPathWithinPattern("/test/a?c/aa", "/test/abc/aa"));// abc/aa
        System.out.println(matcher.extractPathWithinPattern("/test/aa?c/aa/cc", "/test/abc/aa"));// abc/aa
    }

5. extractUriTemplateVariables

路徑必須完全匹配(否則拋出異常),并提取路徑中的路徑參數(shù)值。

示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.extractPathWithinPattern("/test/*", "/test"));//
        System.out.println(matcher.extractPathWithinPattern("/test/*", "/test/aa"));// aa
        System.out.println(matcher.extractPathWithinPattern("/test/**", "/test/aa/bb"));// aa/bb
        System.out.println(matcher.extractPathWithinPattern("/test/a?c/aa", "/test/abc/aa"));// abc/aa
        System.out.println(matcher.extractPathWithinPattern("/test/aa?c/aa/cc", "/test/abc/aa"));// abc/aa
    }

6. getPatternComparator

得到一個(gè)排序比較器。

public Comparator<String> getPatternComparator(String path) {
		return new AntPatternComparator(path);
	}

7. combine

合并兩個(gè)模式。 示例:

    public static void main(String[] args) {
        AntPathMatcher matcher = new AntPathMatcher();
        System.out.println(matcher.combine("/test/*", "/test/aa"));// /test/aa
        System.out.println(matcher.combine("/test/*", "/test/aa/bb"));// /test/test/aa/bb
        System.out.println(matcher.combine("/test/**", "/test/aa"));// /test/aa
        System.out.println(matcher.combine("/test/{id}", "/test/aa"));// /test/{id}/test/aa
    }

到此這篇關(guān)于Spring中的路徑匹配器AntPathMatcher詳解的文章就介紹到這了,更多相關(guān)AntPathMatcher詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)單人版五子棋游戲

    java實(shí)現(xiàn)單人版五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)五子棋小游戲的相關(guān)資料,十分簡(jiǎn)單實(shí)用,有不錯(cuò)的參考借鑒價(jià)值,推薦給大家,需要的朋友可以參考下
    2016-02-02
  • Java框架Quartz中的Trigger簡(jiǎn)析

    Java框架Quartz中的Trigger簡(jiǎn)析

    這篇文章主要介紹了Java框架Quartz中的Trigger簡(jiǎn)析,所有類(lèi)型的trigger都有TriggerKey這個(gè)屬性,表示trigger的身份;除此之外,trigger還有很多其它的公共屬性,這些屬性,在構(gòu)建trigger的時(shí)候可以通過(guò)TriggerBuilder設(shè)置,需要的朋友可以參考下
    2023-11-11
  • Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例

    Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例

    SQLite是一種嵌入式數(shù)據(jù)庫(kù)引擎,可以在各種平臺(tái)上使用,本文主要介紹了Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Java里遍歷Map集合的多種方法總結(jié)

    Java里遍歷Map集合的多種方法總結(jié)

    Java中的Map是一種鍵值對(duì)映射的數(shù)據(jù)結(jié)構(gòu),它提供了一些常用的方法用于獲取、添加、刪除和修改元素,在Java中,有多種方式可以遍歷Map,本文將介紹其中的四種常用方式,并比較它們之間的優(yōu)缺點(diǎn),需要的朋友可以參考下
    2024-07-07
  • maven依賴版本沖突如何處理

    maven依賴版本沖突如何處理

    文章主要介紹了Maven依賴版本沖突的原因以及如何處理版本沖突的方法,包括使用exclusions排除依賴和使用dependencyManagement鎖定版本號(hào)
    2025-01-01
  • idea添加數(shù)據(jù)庫(kù)圖文教程

    idea添加數(shù)據(jù)庫(kù)圖文教程

    這篇文章主要介紹了idea添加數(shù)據(jù)庫(kù)圖文教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Java中獲取時(shí)間戳的三種方式對(duì)比實(shí)現(xiàn)

    Java中獲取時(shí)間戳的三種方式對(duì)比實(shí)現(xiàn)

    這篇文章主要介紹了Java中獲取時(shí)間戳的三種方式對(duì)比實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java中實(shí)現(xiàn)分布式定時(shí)任務(wù)的方法

    Java中實(shí)現(xiàn)分布式定時(shí)任務(wù)的方法

    這篇文章主要介紹了Java中實(shí)現(xiàn)分布式定時(shí)任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • springboot實(shí)現(xiàn)maven多模塊和打包部署

    springboot實(shí)現(xiàn)maven多模塊和打包部署

    本文主要介紹了springboot實(shí)現(xiàn)maven多模塊和打包部署,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • SpringBoot整合RabbitMQ實(shí)現(xiàn)交換機(jī)與隊(duì)列的綁定

    SpringBoot整合RabbitMQ實(shí)現(xiàn)交換機(jī)與隊(duì)列的綁定

    這篇文章將通過(guò)幾個(gè)實(shí)例為大家介紹一些SpringBoot中RabbitMQ如何綁定交換機(jī)(交換器)與隊(duì)列,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-05-05

最新評(píng)論