Spring5 里邊的新玩法叮贩!這種 URL 請求讓我漲見識了击狮!

Spring5 也已經出來好久了,里邊有一些新玩法也需要我們去慢慢揭開面紗益老,這不彪蓬,松哥最近在研究 SpringMVC 源碼的時候,就看到這樣一段代碼:

protected String initLookupPath(HttpServletRequest request) {
    if (usesPathPatterns()) {
        request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
        RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
        String lookupPath = requestPath.pathWithinApplication().value();
        return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
    }
    else {
        return getUrlPathHelper().resolveAndCacheLookupPath(request);
    }
}

這個方法就是 Spring5 里邊出來的捺萌,以前是沒有這個方法的档冬。在舊的 SpringMVC 中,當我們需要獲取當前請求地址的時候桃纯,直接通過如下方式獲瓤崾摹:

String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);

但是現在變了,現在獲取當前請求 URL 地址時态坦,方式如下:

String lookupPath = initLookupPath(request);

兩種方式相比盐数,主要是 initLookupPath 方法中多了 usesPathPatterns 選項,這是 Spring5 中的新玩意伞梯,所以今天松哥就通過一篇簡單的文章來和大家分享一下 usesPathPatterns 到底是什么玫氢,該怎么玩!

這可不是一個小變化哦壮锻!特別是如果你在項目中使用了 WebFlux琐旁,那么這個東西就顯得尤為重要了!

AntPathMatcher

當我們使用 @RequestMapping 注解去標記請求接口的時候(或者使用它的類似方法如 @GetMapping猜绣、@PostMapping灰殴、@PutMapping、@DeleteMapping、@PatchMapping)牺陶,我們可以使用一些通配符去匹配 URL 地址伟阔,舉個簡單例子,假設我有下面五個接口:

@GetMapping("/hello/**/hello")
public String hello() {
    return "/hello/**/hello";
}
@GetMapping("/h?llo")
public String hello2() {
    return "/h?llo";
}
@GetMapping("/**/*.html")
public String hello3() {
    return "/**/*.html";
}
@GetMapping("/hello/{p1}/{p2}")
public String hello4(@PathVariable String p1, @PathVariable String p2) {
    System.out.println("p1 = " + p1);
    System.out.println("p2 = " + p2);
    return "/hello/{p1}/{p2}";
}
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
    System.out.println("name = " + name);
    System.out.println("version = " + version);
    System.out.println("ext = " + ext);
}

在解釋接口的含義之前掰伸,先來說說這幾個通配符的含義:

通配符 含義
** 匹配0個或者多個目錄
* 匹配0個或者多個字符
? 匹配任意單個字符

了解了通配符的含義皱炉,我們再來說說各個接口都能接收哪些請求:

  • 第一個接口,可以接收諸如 /hello/123/123/hello狮鸭、/hello/a/hello 以及 /hello/hello 這樣的請求合搅,因為中間的 ** 代表 0 個或者多個目錄。
  • 第二個接口歧蕉,可以接收諸如 /hallo灾部、/hello/hMllo 之類的請求惯退,注意它不能接收 /haallo 或者 /hllo赌髓,因為 ? 表示一個字符。
  • 第三個接口可以接收任意以 .html 為后綴的請求催跪,例如 /aaa/bb/cc.html锁蠕、/aa.html 或者 /aa/aa.html
  • 第四個接口估計大家都比較熟悉懊蒸,在 RESTful 風格的接口設計中估計大家都用過荣倾,它接收的請求格式類似于 /hello/aa/bb,其中參數 p1 就對應 aa榛鼎,參數 p2 對應 bb逃呼。
  • 第五個接口則用到了正則,name者娱、version 以及 ext 三個參數格式用正則表達出來抡笼,它可以接收諸如 /spring-web-3.0.5.jar 格式的請求,最終的參數 name 就是 spring-web黄鳍,version 就是 3.0.5推姻,ext 則是 .jar

這是 SpringMVC 中之前就存在的功能框沟,不管你用沒用過藏古,反正它一致存在。

那么是誰支撐了這個功能呢忍燥?那就是 AntPathMatcher拧晕。

AntPathMatcher 是一個實現了 Ant 風格的路徑匹配器,Ant 風格的路徑規(guī)則實際上就是我們前面給大家介紹的那三種路徑匹配符梅垄,很 Easy厂捞。這種路徑匹配規(guī)則源自 Apache Ant 項目(https://ant.apache.org),Apache Ant 我們現在其實已經很少會用到了,它的替代品就是大家所熟知的 Maven靡馁,如果你有幸維護一些 2010 年之前的老項目的話欲鹏,有可能會接觸到 Ant。

AntPathMatcher 實際上在 SpringMVC 中有非常廣泛的應用臭墨,不僅僅是在 @RequestMapping 中定義接口用到赔嚎,在其他一些涉及到地址匹配的地方也會用到,例如我們在 SpringMVC 的配置文件中配置靜態(tài)資源過濾時胧弛,也是 Ant 風格路徑匹配:

<mvc:resources mapping="/**" location="/"/>

另外像攔截器里的攔截路徑注冊尤误、跨域處理時的路徑匹配等等,都會用到 Ant 風格的路徑匹配符叶圃。

整體上來說袄膏,AntPathMatcher 是 Spring 中一種比較原始的路徑匹配解決方案,雖然比較簡單掺冠,但是它的效率很低,并且在處理 URL 編碼的時候也很不方便码党。

因此德崭,才有了 Spring5 中的 PathPattern。

PathPattern

PathPattern 專為 Web 應用設計揖盘,它與之前的 AntPathMatcher 功能大部分比較類似眉厨,當然也有一些細微差異,這個松哥后面會說兽狭。

如果是 Servlet 應用憾股,目前官方推薦的 URL 匹配解決方案就是 PathPattern(當然你也可以選擇較早的 AntPathMatcher),雖然官方推薦的是 PathPattern箕慧,但實際上默認使用的依然是 AntPathMatcher服球;如果你用的是 WebFlux,PathPattern 就是唯一解決方案了颠焦。

注意斩熊,PathPattern 是一個非常新鮮的玩藝,目前 Spring 最新版是 5.3.4伐庭,在 Spring5.3 之前粉渠,我們在 Servlet 應用中,也只能選擇 AntPathMatcher圾另,從 Spring5.3 之后霸株,我們才可以使用 PathPattern 了。

PathPattern 會將 URL 規(guī)則預解析為 PathContainer集乔,它對 URL 地址匹配的處理更加快速去件,PathPattern 與 AntPathMatcher 的差異主要體現在兩個方面:

第一,PathPattern 只支持結尾部分使用 **,如果在路徑的中間使用 ** 就會報錯箫攀,上文中第一個和第三個接口肠牲,在 PathPattern 模式下會報錯,如下:

image

因為在中間或者開始使用 ** 極易造成混亂靴跛,因此 PathPattern 只支持在結尾使用 **缀雳。

第二,PathPattern 支持使用諸如 {*path} 的方式進行路徑匹配梢睛,這種寫法也可以匹配到多層路徑肥印,并且將匹配到的值賦值給 path 變量,例如如下一個接口:

@GetMapping("/javaboy/{*path}")
public void hello6(@PathVariable String path) {
    System.out.println("path = " + path);
}

如果請求路徑是 http://localhost:8080/javaboy/aa绝葡,那么參數 path 的值就是 /aa深碱;

如果請求路徑是 http://localhost:8080/javaboy/aa/bb/cc/dd,那么參數 path 的值就是 /aa/bb/cc/dd藏畅;

這個寫法也比較新穎敷硅,因為之前的 AntPathMatcher 里邊沒有這個。

如何使用

默認情況下愉阎,SpringMVC 中使用的還是 AntPathMatcher绞蹦,那么如何開啟 PathPattern 呢?很簡單榜旦,在 SpringBoot 項目中只需要添加如下配置即可:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setPatternParser(new PathPatternParser());
    }
}

添加了這個配置后幽七,在我們文章一開始貼出來的代碼里,就會進入到 if 分支中溅呢,進而使用 PathPattern 去解析請求 URL澡屡。

小結

好啦,今天就和小伙伴們聊這么多咐旧,大家可以體驗一把這個東東驶鹉,不過注意選擇 Spring 的版本哦,一定選擇 5.3 之上的版本~大家周末愉快哦~

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末休偶,一起剝皮案震驚了整個濱河市梁厉,隨后出現的幾起案子,更是在濱河造成了極大的恐慌踏兜,老刑警劉巖词顾,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異碱妆,居然都是意外死亡肉盹,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門疹尾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來上忍,“玉大人骤肛,你說我怎么就攤上這事∏侠叮” “怎么了腋颠?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吓笙。 經常有香客問我淑玫,道長,這世上最難降的妖魔是什么面睛? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任絮蒿,我火速辦了婚禮,結果婚禮上叁鉴,老公的妹妹穿的比我還像新娘土涝。我一直安慰自己,他們只是感情好幌墓,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布但壮。 她就那樣靜靜地躺著,像睡著了一般克锣。 火紅的嫁衣襯著肌膚如雪茵肃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天袭祟,我揣著相機與錄音,去河邊找鬼捞附。 笑死巾乳,一個胖子當著我的面吹牛,可吹牛的內容都是我干的鸟召。 我是一名探鬼主播胆绊,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欧募!你這毒婦竟也來了压状?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤跟继,失蹤者是張志新(化名)和其女友劉穎种冬,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體舔糖,經...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡娱两,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了金吗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片十兢。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡趣竣,死狀恐怖,靈堂內的尸體忽然破棺而出旱物,到底是詐尸還是另有隱情遥缕,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布宵呛,位于F島的核電站单匣,受9級特大地震影響,放射性物質發(fā)生泄漏烤蜕。R本人自食惡果不足惜封孙,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讽营。 院中可真熱鬧虎忌,春花似錦、人聲如沸橱鹏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莉兰。三九已至挑围,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間糖荒,已是汗流浹背杉辙。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捶朵,地道東北人蜘矢。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像综看,于是被迫代替她去往敵國和親品腹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容