WebFlux中的Path參數(shù)解析與url映射是怎樣的,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

在分宜等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供做網(wǎng)站、網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營銷推廣,外貿(mào)網(wǎng)站建設(shè),分宜網(wǎng)站建設(shè)費(fèi)用合理。
WebFlux 之 Path 參數(shù)解析與 url 映射
異步、反應(yīng)式、函數(shù)式編程,近來可以說是逐漸主流了;Spring5 通過 Reactor 增加了對(duì)反應(yīng)式編程的支持,而 Spring WebFlux 不同于以往的 web 框架,作為一個(gè)非阻塞異步 web 框架,可以充分的利用多核 CPU 硬件資源,提供更強(qiáng)的并發(fā)支持;Spring 官方對(duì) WebFlux 的支持非常友好,基本上對(duì)于慣于 Spring WEB 的 java 開發(fā)者,可以很簡單的遷移過來
接下來我們將進(jìn)入 WebFlux 系列教程,努力使用最簡明的語言,來介紹一下 WebFlux 的基本玩法,讓各位小伙伴可以順暢的切換和使用 WebFlux 來體驗(yàn)反應(yīng)式編程的魅力
小編將主要介紹 WebFlux 提供 web 接口時(shí)的 url 匹配,以及對(duì)應(yīng)的 path 參數(shù)解析
本項(xiàng)目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA進(jìn)行開發(fā)
使用 WebFlux,最主要的引入依賴如下(省略掉了 SpringBoot 的相關(guān)依賴,如對(duì)于如何創(chuàng)建 SpringBoot 項(xiàng)目不太清楚的小伙伴,可以關(guān)注一下我之前的博文)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> </dependencies>
下面所有內(nèi)容基于官方文檔完成: https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-requestmapping-uri-templates
下面的示例主要是基于注解的方式,基本知識(shí)點(diǎn)和 SpringWeb 沒有太大的區(qū)別(至于函數(shù)式的用法,后面會(huì)專門介紹)
path 參數(shù),舉例如: http://127.0.0.1:8080/name/test中name和test就算是 path 參數(shù),我們主要是借助@PathVariable來獲取
一個(gè)具體實(shí)例
@RestController
@RequestMapping(path = "path")
public class PathAction {
    /**
     * 最基本的path獲取方式
     *
     * @param index
     * @return
     */
    @GetMapping(path = "/basic/{index}")
    public Mono<String> basic(@PathVariable(name = "index") int index) {
        return Mono.just("path index: " + index);
    }
}針對(duì)上面的 case,我們簡單的設(shè)計(jì)了三個(gè)訪問 case,具體結(jié)果如下
?  ~ curl 'http://127.0.0.1:8080/path/basic/1'
path index: 1%
?  ~ curl 'http://127.0.0.1:8080/path/basic/1/2'
{"timestamp":"2020-08-26T13:35:26.221+0000","path":"/path/basic/1/2","status":404,"error":"Not Found","message":null,"requestId":"8256bf73"}%
?  ~ curl 'http://127.0.0.1:8080/path/basic/'
{"timestamp":"2020-08-26T13:35:32.196+0000","path":"/path/basic/","status":404,"error":"Not Found","message":null,"requestId":"eeda1111"}%請(qǐng)注意上面的輸出,/basic/{index} 只能匹配單級(jí)的 path 路徑參數(shù),而且上面的寫法中,這級(jí) path 路徑必須存在
查看PathVariable注解可以看到里面有一個(gè)required屬性,如果設(shè)置為 false,會(huì)怎樣呢
@GetMapping(path = "/basic2/{index}")
public Mono<String> basic2(@PathVariable(name = "index", required = false) Integer index) {
    return Mono.just("basic2 index: " + index);
}測試 case 如下
?  ~ curl 'http://127.0.0.1:8080/path/basic2/'
{"timestamp":"2020-08-26T13:41:40.100+0000","path":"/path/basic2/","status":404,"error":"Not Found","message":null,"requestId":"b2729e2c"}%
?  ~ curl 'http://127.0.0.1:8080/path/basic2/22'
basic2 index: 22%
?  ~ curl 'http://127.0.0.1:8080/path/basic2/22/3'
{"timestamp":"2020-08-26T13:41:44.400+0000","path":"/path/basic2/22/3","status":404,"error":"Not Found","message":null,"requestId":"0b3f173c"}%從上面的實(shí)際 case,也可以看出來,級(jí)別這個(gè)屬性設(shè)置為 false,但是 url 路徑依然需要正確匹配,多一級(jí)和少一級(jí)都不行
上面只有一個(gè) path 參數(shù),如果有多個(gè)參數(shù),也比較簡單
/**
 * 多個(gè)參數(shù)的場景
 *
 * @param index
 * @param order
 * @return
 */
@GetMapping(path = "/mbasic/{index}/{order}")
public Mono<String> mbasic(@PathVariable(name = "index") int index, @PathVariable(name = "order") String order) {
    return Mono.just("mpath arguments: " + index + " | " + order);
}測試 case 如下
? ~ curl 'http://127.0.0.1:8080/path/mbasic/1/asc' mpath arguments: 1 | asc%
上面的兩個(gè) case,都是完整的匹配某一級(jí)路徑,下面介紹部分匹配的 case
/**
 * 路徑中的部分內(nèi)容匹配
 *
 * - /part/test.txt -> name = test
 * - /part/a/test.txt -> 不匹配
 *
 * @param name
 * @return
 */
@GetMapping(path = "/part/{name}.txt")
public Mono<String> part(@PathVariable(name = "name") String name) {
    return Mono.just("part path argument: " + name);
}請(qǐng)注意上面的 path 路徑,后綴是.txt,如下面的實(shí)例中part/hello.txt中那么對(duì)應(yīng)的就是hello
?  ~ curl 'http://127.0.0.1:8080/path/part/hello.txt'
part path argument: hello%
?  ~ curl 'http://127.0.0.1:8080/path/part/hello.tx'
{"timestamp":"2020-08-26T13:47:49.121+0000","path":"/path/part/hello.tx","status":404,"error":"Not Found","message":null,"requestId":"1075d683"}%接下來更高端的 path 參數(shù)匹配來了,支持一些簡單的正則,如我們希望對(duì)spring-web-3.0.5.jar這段 path 路徑進(jìn)行解析,希望將spring-web作為name, 3.0.5作為version,.jar作為ext
因此我們的 rest 接口寫法可以如下
/**
 * 正則匹配
 *
 * /path/path/pattern/spring-web-3.0.5.jar  -> name = spring-web,  version=3.0.5,  ext=.jar
 *
 * @return
 */
@GetMapping(path = "/pattern/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public Mono<String> urlPattern(@PathVariable(name = "name") String name,
        @PathVariable(name = "version") String version, @PathVariable(name = "ext") String ext) {
    return Mono.just("pattern arguments name=" + name + " version=" + version + " ext=" + ext);
}注意上面的所有寫法,都有一個(gè)特點(diǎn),那就是只能針對(duì)單級(jí)的 path 路徑進(jìn)行全/部分匹配(本文中將 path 路徑中//之間作為一級(jí)),那么如果我希望我的 path 參數(shù)可以匹配多級(jí),可以怎么辦
如 /path/name/hello 請(qǐng)求路徑中,我希望將 /name/hello 作為一個(gè) path 參數(shù)
針對(duì)上面的場景,我們主要是借助{*name}方式來處理,注意這個(gè)參數(shù)名前面的*號(hào)
/**
 * 匹配:
 *
 * - /path/pattern2  -> name == ""
 * - /path/pattern2/hello  -> name == /hello
 * - /path/pattern2/test/hello -> name = /test/hello
 *
 * @param name
 * @return
 */
@GetMapping(path = "/pattern2/{*name}")
public Mono<String> pattern2(@PathVariable(name = "name") String name) {
    return Mono.just("pattern2 argument: " + name);
}測試 case 如下
? ~ curl 'http://127.0.0.1:8080/path/pattern2' pattern2 argument: % ? ~ curl 'http://127.0.0.1:8080/path/pattern2/hello' pattern2 argument: /hello% ? ~ curl 'http://127.0.0.1:8080/path/pattern2/hello/world' pattern2 argument: /hello/world%
前面介紹的是 path 參數(shù)解析,接下來我們簡單的看一下最常見的三種路徑匹配方式
一個(gè)星號(hào),表示匹配 0 個(gè) or1 個(gè)單級(jí) path 路徑
/**
 * 單個(gè)*號(hào),只能匹配一級(jí)目錄,注意這種方式與上面的 pattern2 之間的區(qū)別
 *
 * 可以匹配:
 *
 * - /path/pattern3/hello
 * - /path/pattern3
 *
 * 不能匹配
 *
 * - /path/pattern3/hello/1
 *
 * @return
 */
@GetMapping(path = "/pattern3/*")
public Mono<String> pattern3() {
    return Mono.just("pattern3 succeed!");
}實(shí)測 case 如下
# 請(qǐng)注意,這里是沒有/結(jié)尾的
?  ~ curl 'http://127.0.0.1:8080/path/pattern3'
{"timestamp":"2020-08-27T00:01:20.703+0000","path":"/path/pattern3","status":404,"error":"Not Found","message":null,"requestId":"c88f5066"}%
?  ~ curl 'http://127.0.0.1:8080/path/pattern3/'
pattern3 succeed!%
?  ~ curl 'http://127.0.0.1:8080/path/pattern3/a'
pattern3 succeed!%
?  ~ curl 'http://127.0.0.1:8080/path/pattern3/a/b'
{"timestamp":"2020-08-27T00:01:18.144+0000","path":"/path/pattern3/a/b","status":404,"error":"Not Found","message":null,"requestId":"203dc7d4"}%請(qǐng)注意上面的實(shí)例,/path/pattern3 訪問 404, 而/path/pattern3/是可以的,唯一的區(qū)別就是多了一個(gè)后綴/
why?
是因?yàn)?path 路徑的星號(hào)前面有一個(gè)/導(dǎo)致的么?
接下來我們?cè)僭O(shè)計(jì)一個(gè) case,將*前面的/干掉,再測試一下
@GetMapping(path = "/pattern33**")
public Mono<String> pattern33() {
    return Mono.just("pattern33 succeed!");
}再次測試,結(jié)果如下
?  ~ curl 'http://127.0.0.1:8080/path/pattern3311'
pattern33 succeed!%
?  ~ curl 'http://127.0.0.1:8080/path/pattern33/11'
{"timestamp":"2020-08-27T00:05:51.236+0000","path":"/path/pattern33/11","status":404,"error":"Not Found","message":null,"requestId":"d8cbd546"}%
?  ~ curl 'http://127.0.0.1:8080/path/pattern33'
pattern33 succeed!%
?  ~ curl 'http://127.0.0.1:8080/path/pattern331/'
pattern33 succeed!%借助前面兩個(gè) case,我們基本上可以看出*的作用
*前面的完全匹配
比如/pattern3/*,那么訪問的 path 路徑前綴必須是/pattern3/
*最多表示單級(jí)路徑,簡單來講就是*所代表的的位置中不能出現(xiàn)/x
比如/pattern33**,那么/pattern331/可以匹配,但是/pattern331/1不能
有別與上面的單個(gè)*匹配 0-1 級(jí) path 路徑,兩個(gè)**則表示可以一直匹配到最后一層
/**
 * 對(duì)于 pattern4開頭的都可以匹配
 *
 * @return
 */
@GetMapping(path = "/pattern4/**")
public Mono<String> pattern4() {
    return Mono.just("pattern4 succeed!");
}測試 case 如下
? ~ curl 'http://127.0.0.1:8080/path/pattern4' pattern4 succeed!% ? ~ curl 'http://127.0.0.1:8080/path/pattern4/12' pattern4 succeed!% ? ~ curl 'http://127.0.0.1:8080/path/pattern4/12/3' pattern4 succeed!%
請(qǐng)注意
直接訪問/pattern4也是可以命中的,這個(gè)和上面是有區(qū)別的
單個(gè)字符的通配,比較簡單如下
/**
 * 匹配  pattern5/test   pattern5/tast ...
 * 不匹配 pattern5/tst pattern5/tesst
 *
 * @return
 */
@GetMapping(path = "/pattern5/t?st")
public Mono<String> pattern5() {
    return Mono.just("pattern5 succeed!");
}訪問 case
?  ~ curl 'http://127.0.0.1:8080/path/pattern5/test'
pattern5 succeed!%
?  ~ curl 'http://127.0.0.1:8080/path/pattern5/t/st'
{"timestamp":"2020-08-27T00:13:42.557+0000","path":"/path/pattern5/t/st","status":404,"error":"Not Found","message":null,"requestId":"add34639"}%
?  ~ curl 'http://127.0.0.1:8080/path/pattern5/tst'
{"timestamp":"2020-08-27T00:14:01.078+0000","path":"/path/pattern5/tst","status":404,"error":"Not Found","message":null,"requestId":"b2691121"}%從上面的測試輸出也可以看出
? 對(duì)應(yīng)的地方不能是/以及其他不被支持的字符(如?,',", %等)
? 對(duì)應(yīng)的地方必須存在
雖然本文的主題是 webflux 中 path 參數(shù)解析與 url 映射匹配,但是看下來我們會(huì)神奇的發(fā)現(xiàn),這些知識(shí)點(diǎn)和 SpringMVC 中,貌似也沒有什么區(qū)別,事實(shí)上也確實(shí)如此;對(duì)于注解的使用場景時(shí),絕大多數(shù),都是之前怎么玩,現(xiàn)在依然可以怎么玩
下面用一個(gè)表格針對(duì)上面的知識(shí)點(diǎn)進(jìn)行匯總
| pattern | 描述 | 舉例 | 
|---|---|---|
? | 匹配一個(gè)字符 | pages/t?st.html 匹配 /pages/test.html and /pages/t3st.html | 
* | 匹配單級(jí) path 路徑中 0-多個(gè)字符 | "/resources/*.png" matches "/resources/file.png" <br/> "/projects/*/versions" matches "/projects/spring/versions" but does not match "/projects/spring/boot/versions" | 
** | 匹配 0-多個(gè) path 路徑 | "/resources/**" matches "/resources/file.png" and "/resources/images/file.png" <br/> 而"/resources/**/file.png"這種寫法是非法的 | 
{name} | 匹配單級(jí) path 路徑參數(shù) | "/projects/{project}/versions" matches "/projects/spring/versions" and captures project=spring | 
{name:[a-z]+} | 正則 | "/projects/{project:[a-z]+}/versions" matches "/projects/spring/versions" but not "/projects/spring1/versions" | 
{*path} | 匹配 path 路徑中,0-最后一級(jí) path 路徑參數(shù) | "/resources/{*file}" matches "/resources/images/file.png" and captures file=images/file.png | 
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。
                當(dāng)前題目:WebFlux中的Path參數(shù)解析與url映射是怎樣的
                
                當(dāng)前網(wǎng)址:http://www.chinadenli.net/article18/iigodp.html
            
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、服務(wù)器托管、App開發(fā)、自適應(yīng)網(wǎng)站、網(wǎng)頁設(shè)計(jì)公司、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)