1. 程式人生 > 其它 >【SpringMVC從入門到精通】01-@RequestMapping註解

【SpringMVC從入門到精通】01-@RequestMapping註解

筆記來源:【尚矽谷】SpringMVC教程丨一套快速上手spring mvc

目錄

@RequestMapping 註解

1、功能

從註解名稱上我們可以看到,@RequestMapping註解的作用就是將請求和處理請求的控制器方法關聯起來,建立對映關係

SpringMVC 接收到指定的請求,就會來找到在對映關係中對應的控制器方法來處理這個請求

控制器中有多個方法對應同一個請求的情況

這是一種特殊情況,我們定義至少兩個控制類,其中定義的控制器方法上@ReqeustMapping指定同一請求路徑

@Controller
public class HelloController {
    @RequestMapping("/")
    public String index() {
        return "index";
    }
}
@Controller
public class RequestMappingController {
    @RequestMapping("/")
    public String index() {
        return "target";
    }
}

如果存在兩個或多個控制器,其控制器方法的@RequestMapping一致,即多個控制器方法試圖都想要處理同一個請求時,這時啟動 Tomcat 時會丟擲BeanCreationException異常,並指明There is already 'helloController' bean method即 helloController 中存在處理同意請求的控制器方法

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'requestMappingController' method 
com.vectorx.springmvc.s00_helloworld.RequestMappingController#index()
to { [/]}: There is already 'helloController' bean method
com.vectorx.springmvc.s00_helloworld.HelloController#index() mapped.

但是這顯然是不合理的,當一個系統方法很多,很難完全避免兩個或多個同名方法的存在,那該怎麼辦呢?

2、位置

檢視@RequestMapping註解的原始碼,可以清楚地看到@Target中有TYPEMETHOD兩個屬性值,表示其可以作用在類或方法上

也就是說@RequestMapping不僅可以在控制器方法上進行使用,也可以在控制器類上進行使用。那兩種方式有什麼區別呢?

  • @RequestMapping標識一個類:設定對映請求的請求路徑的初始資訊
  • @RequestMapping標識一個方法:設定對映請求的請求路徑的具體資訊
@Controller
@RequestMapping("/requestMappingController")
public class RequestMappingController {
    @RequestMapping("/success")
    public String success() {
        return "success";
    }
}

前臺建立超連結,超連結跳轉路徑 = 控制器上@RequestMapping對映請求的初始路徑 + 控制器方法上@RequestMapping對映請求的具體路徑,即/requestMappingController/success,再將其使用Tymeleaf@{}語法包裹起來,這樣Tymeleaf會為我們自動加上上下文路徑

<a th:href="@{/requestMappingController/success}">訪問指定頁面success.html</a>

測試結果

這樣就可以為不同的控制器方法,在設定對映請求的請求路徑時,指定不同的初始資訊,從而避免控制器中有多個方法對應同一個請求的情況,這也就解決了之前的問題

3、value 屬性

@RequestMapping註解的value屬性有哪些用途呢?

  • 請求對映:通過請求的請求地址匹配請求對映
  • 匹配多個請求:是一個字串型別的陣列,表示該請求對映能夠匹配多個請求地址所對應的
  • 必須設定:至少通過一個請求地址匹配請求對映

匹配多個請求

檢視@RequestMapping註解的原始碼,會發現其value屬性返回值為 String 型別的陣列,這也說明了之所以@RequestMapping註解的value屬性可以匹配多個請求的原因。通過為value屬性指定多個值的方式,就可以對個多個請求建立請求對映

在控制器方法上的@RequestMapping中新增一個/test請求對映

@RequestMapping(value = {"/success", "/test"})
public String success() {
    return "success";
}

前臺建立一個/test的請求路徑的超連結,以便進行測試

<a th:href="@{/requestMappingController/test}">>測試RequestMapping註解的value屬性-->/test</a>

測試結果

這樣,同一個控制器方法就可以實現對多個請求進行統一處理

4、method 屬性

@RequestMapping註解的method屬性有哪些用途呢?

  • 通過請求的請求方式(GETPOST)匹配請求對映

1、常用的請求方式有 4 種:GET、POST、PUT、DELETE

  • GET 用於查詢資料
  • POST 用於新增資料
  • PUT 用於更新資料
  • DELETE 使用者刪除資料

但是很多情況下,習慣上會讓 POST 承擔更多的職責,即通過 POST 進行增、刪、改的操作,可以說是“一個人攬了三個人的活”

2、還有 4 種不常用的請求:HEAD、PATCH、OPTIONS、TRACE

  • HEAD 獲取響應的報頭,檢查超連結的有效性、網頁是否被修改,多用於自動搜尋機器人獲取網頁的標誌資訊,獲取 rss 種子資訊,或者傳遞安全認證資訊等
  • PATCH 用於更新資料
  • OPTIONS 用於測試伺服器,解決同源策略和跨域請求問題
  • TRACE 用於測試或診斷

有的資料還會介紹 CONNECT 請求,好像用於 HTTP 代理的,很少人聽過,當然用的更少(我也是剛知道,有懂的求科普)

  • 是一個RequestMethod型別的陣列,表示該請求對映能夠匹配多種請求方式的請求

原始碼為證:RequestMethod[] method() default {};

同時注意到method屬性預設值為空陣列,是否說明控制器方法不新增method屬性時,不同的請求方法都能夠匹配呢?

1)無 method 時匹配哪些請求方式?

通過測試驗證猜想

<a th:href="@{/requestMappingController/test}">測試RequestMapping註解的method屬性-->GET</a>
<br/>
<form th:action="@{/requestMappingController/test}" method="post">
    <input type="submit" value="測試RequestMapping註解的method屬性-->POST">
</form>

測試結果:事實證明,控制器方法不新增method屬性時,可以接收GETPOST的請求,那麼應該是預設不對請求方式限制了

本著嚴謹的態度,再測試下是否在不新增method屬性時,預設也支援PUTDELETE請求

不過,PUTDELETE請求比較特殊,需要使用到隱藏域,且method固定為POST

<form th:action="@{/requestMappingController/test}" method="post">
    <input type="hidden" name="_method" value="put"/>
    <input type="submit" value="測試RequestMapping註解的method屬性-->PUT">
</form>
<br/>
<form th:action="@{/requestMappingController/test}" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <input type="submit" value="測試RequestMapping註解的method屬性-->DELETE">
</form>

同時在web.xml中需要新增隱藏域請求方式的過濾器配置

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/</url-pattern>
</filter-mapping>

測試結果也是成功的

存疑點:本來也想測試下HEADPTACHOPTIONSTRACE這幾種不常用的請求方式的,但是發現 form 表單好像不支援這些請求方式。即使使用隱藏域,也會變成GET的請求方式。很疑惑這些請求方式要怎麼模擬,有懂的求科普。這裡記錄下,留個印象,以待後續考古o(╯□╰)o

2)不滿足 method 會怎樣?

值得注意的是

若當前請求的請求地址滿足請求對映的value屬性,但是請求方式不滿足method屬性,則瀏覽器報錯

HTTP Status 405 - Request method 'POST' not supported

程式碼驗證

@RequestMapping(value = {"/success", "/test"}, method = RequestMethod.GET)
public String success() {
    return "success";
}

驗證結果:確實報了 405。同理可以將method屬性值中GET改成POSTPUTDELETE對應進行驗證即可,這裡就不一一驗證了

雖然無關緊要,但就是好奇為嘛我的是中文提示(灬°ω°灬)

發現這個版本 tomcat 的 lib 包中有 i18n 相關 jar 包,原來是做了國際化,“不一定有用”的知識又增加了~

3)派生註解

對於處理指定請求方式的控制器方法,SpringMVC 中提供了@RequestMapping的派生註解

  • 處理GET請求的對映->@GetMapping
  • 處理POST請求的對映->@PostMapping
  • 處理PUT請求的對映->@PutMapping
  • 處理DELETE請求的對映->@DeleteMapping

這裡對於派生註解很容易理解,用數學上的等價解釋就是

\(@GetMapping(value="...") <==> @RequestMapping(value="...", method=RequestMethod.GET)\)

\(@PostMapping(value="...") <==> @RequestMapping(value="...", method=RequestMethod.POST)\)

\(@PutMapping(value="...") <==> @RequestMapping(value="...", method=RequestMethod.PUT)\)

\(@DeleteMapping(value="...") <==> @RequestMapping(value="...", method=RequestMethod.DELETE)\)

通過程式碼進行測試

後臺程式碼

@Controller
@RequestMapping("/requestMappingController")
public class RequestMappingController {
    @GetMapping("/success")
    public String successGet() {
        return "successget";
    }
    @PostMapping("/success")
    public String successPost() {
        return "successpost";
    }
    @PutMapping("/success")
    public String successPut() {
        return "successput";
    }
    @DeleteMapping("/success")
    public String successDelete() {
        return "successdelete";
    }
}

前臺程式碼

<a th:href="@{/requestMappingController/success}">測試GetMapping</a>
<br/><br/>
<form th:action="@{/requestMappingController/success}" method="post">
    <input type="submit" value="測試PostMapping">
</form>
<br/>
<form th:action="@{/requestMappingController/success}" method="post">
    <input type="hidden" name="_method" value="put"/>
    <input type="submit" value="測試PutMapping">
</form>
<br/>
<form th:action="@{/requestMappingController/success}" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <input type="submit" value="測試DeleteMapping">
</form>

別忘了,新增四個測試頁面successget.htmlsuccesspost.htmlsuccessput.htmlsuccessdelete.html,在這個四個不同頁面中標註不同的內容以示區分

驗證結果:可以看到,GET/POST/PUT/DELETE等請求方式,均能夠被正常接收和處理

4)form 表單支援哪些請求方式?

  • 常用的請求方式有GETPOSTPUTDELETE,但是目前瀏覽器只支援GETPOST(OS:剛才還有點疑惑的,這裡好像“水落石出了”)
  • 若在 form 表單提交時,為method設定了其他請求方式的字串(PUTDELETE),則按照預設的GET請求方式處理
  • 若要傳送PUTDELETE請求,則需要通過 Spring 提供的過濾器HiddenHttpMethodFilter,在 restful 部分會講到(OS:我上面剛自己研究了下,沒想到老師這裡會講^_^

如果去除過濾器HiddenHttpMethodFilter的配置,同時註釋掉隱藏域的程式碼,並將methodpost值改成putdelete

<form th:action="@{/requestMappingController/success}" method="put">
    <!--    <input type="hidden" name="_method" value="put"/>-->
    <input type="submit" value="測試PutMapping">
</form>
<br/>
<form th:action="@{/requestMappingController/success}" method="delete">
    <!--    <input type="hidden" name="_method" value="delete"/>-->
    <input type="submit" value="測試DeleteMapping">
</form>

按照上述的說法,會按照預設的GET請求方式處理,這裡進行驗證

可以發現,本應走PUTDELETE方式的請求,都被GET請求方式的控制器方法處理了。如果這裡控制器中連相應GET請求方式都沒有定義的話,肯定是報 405 了。這裡註釋掉@GetMapping的請求方法

//@GetMapping("/success")
//public String successGet() {
//    return "successget";
//}

驗證結果:顯而易見

5、params 屬性

@RequestMapping註解的params屬性通過請求的請求引數匹配請求對映

它是一個字串型別的陣列,可以通過四種表示式設定請求引數和請求對映的匹配關係

  • param:要求請求對映所匹配的請求必須攜帶param請求引數
  • !param:要求請求對映所匹配的請求必須不能攜帶param請求引數
  • param=value:要求請求對映所匹配的請求必須攜帶param請求引數且param=value
  • param!=value:要求請求對映所匹配的請求必須攜帶param請求引數但是param!=value

若當前請求滿足@RequestMapping註解的valuemethod屬性,但是不滿足params屬性,此時頁面顯示400錯誤,即請求不匹配

1)param

這裡指定params的值指定為username,這就要求請求中必須攜帶username的請求引數

@RequestMapping(
    value = {"/testParams"},
    params = {"username"}
)
public String testParams() {
    return "success";
}

前臺測試程式碼:分別不加請求引數和加上請求引數,進行測試

<a th:href="@{/requestMappingController/testParams}">測試RequestMapping註解的params屬性==>testParams</a><br/>
<a th:href="@{/requestMappingController/testParams?username=admin}">測試RequestMapping註解的params屬性==>testParams?username=admin</a>

測試結果

可以發現,當配置了params屬性並指定相應的請求引數時,請求中必須要攜帶相應的請求引數資訊,否則前臺就會報丟擲400的錯誤資訊,符合預期

HTTP Status 400:Parameter conditions "username" not met for actual request parameters

不過在Tymeleaf中使用問號的方式會有錯誤提示,雖然不影響功能,但不想要錯誤提示的話,最好通過(...,...)的方式進行包裹,多個引數間通過,隔開

<a th:href="@{/requestMappingController/testParams(username='admin', password=123456)}">測試RequestMapping註解的params屬性==>testParams(username='admin', password=123456)</a><br/>

測試驗證

可以發現,通過括號包裹的方式,Tymeleaf最終會幫我們將其解析成?username=admin&password=123456的格式

存疑點:實測發現,``testParams(username='admin', password=123456)改成testParams(username=admin, password=123456),即admin`不加單引號也是可以的,這與課堂上所講的並不一致,此點存疑

2)!param

這裡將params = {"username"}username前加上!即可,即params = {"!username"},這就要求請求中的請求引數中不能攜帶username請求引數

@RequestMapping(
    value = {"/testParams"},
    params = {"!username"}
)
public String testParams() {
    return "success";
}

測試結果

可以發現,沒有攜帶username請求引數的請求變得能夠正常訪問,而攜帶了username請求引數的請求反而出現了400的異常資訊,符合預期

HTTP Status 400:Parameter conditions "!username" not met for actual request parameters: username={admin}, password={123456}

3)param=value

這裡params的值指定為username=admin的形式,即要求請求中不僅要攜帶username的請求引數,且值為admin

@RequestMapping(
    value = {"/testParams"},
    params = {"username=admin"}
)
public String testParams() {
    return "success";
}

測試結果

可以發現,不攜帶username請求引數的請求和攜帶username請求引數但不為admin的請求,均提示400的請求錯誤,符合預期

4)param!=value

這裡將params的值指定為username!=admin,即要求請求中不僅要攜帶username的請求引數,且值不能為admin

@RequestMapping(
    value = {"/testParams"},
    params = {"username!=admin"}
)
public String testParams() {
    return "success";
}

測試結果

實際測試結果發現:不攜帶username請求引數的請求和攜帶username請求引數但值不為admin的請求,可以正常訪問;而攜帶username請求引數但值為admin的請求,不能正常訪問,不完全符合預期

存疑點:不攜帶username請求引數的請求能夠正常訪問,這一點不符合課程中講解的內容,此點存疑

6、headers 屬性

@RequestMapping註解的headers屬性通過請求的請求頭資訊匹配請求對映

它是一個字串型別的陣列,可以通過四種表示式設定請求頭資訊和請求對映的匹配關係

  • header:要求請求對映所匹配的請求必須攜帶header請求頭資訊
  • header:要求請求對映所匹配的請求必須不能攜帶header請求頭資訊
  • header=value:要求請求對映所匹配的請求必須攜帶header請求頭資訊且header=value
  • header!=value:要求請求對映所匹配的請求必須攜帶header請求頭資訊且header!=value

若當前請求滿足@RequestMapping註解的valuemethod屬性,但是不滿足headers屬性,此時頁面顯示404錯誤,即資源未找到

測試程式碼

@RequestMapping(
    value = {"/testHeaders"},
    headers = {"Host=localhost:8081"}
)
public String testHeaders() {
    return "success";
}

測試結果

因為我本地tomcat啟動埠是8080,所以是匹配不成功的,此時顯示404錯誤,符合預期

再將埠號修改為8080

@RequestMapping(
    value = {"/testHeaders"},
    headers = {"Host=localhost:8080"}
)
public String testHeaders() {
    return "success";
}

測試結果

這一次,因為埠號一致,所以成功跳轉,符合預期

7、Ant 風格路徑

  • ?:表示任意的單個字元
  • *:表示任意的0個或多個字元
  • **:表示任意的一層或多層目錄。注意:在使用**時,只能使用/**/xxx的方式

探子來報:**經實測,0 層目錄也可以,這裡嚴謹來說,應該是“表示任意層目錄”

1)?

後臺測試程式碼

//ant風格路徑
@RequestMapping("/a?a/testAnt")
public String testAnt() {
    return "success";
}

前臺測試程式碼

Ant風格路徑——?:<br/>
<a th:href="@{/requestMappingController/testAnt}">測試ant風格路徑_/a?a/testAnt==>/testAnt</a><br/>
<a th:href="@{/requestMappingController/a1a/testAnt}">測試ant風格路徑_/a?a/testAnt==>/a1a/testAnt</a><br/>
<a th:href="@{/requestMappingController/aaa/testAnt}">測試ant風格路徑_/a?a/testAnt==>/aaa/testAnt</a><br/>
<a th:href="@{/requestMappingController/aaaa/testAnt}">測試ant風格路徑_/a?a/testAnt==>/aaaa/testAnt</a><br/>
<a th:href="@{/requestMappingController/a/a/testAnt}">測試ant風格路徑_/a?a/testAnt==>/a/a/testAnt</a><br/>
<a th:href="@{/requestMappingController/a?a/testAnt}">測試ant風格路徑_/a?a/testAnt==>/a?a/testAnt</a><br/>

測試結果

可以發現,/a?a/testAnt能夠匹配的路徑有

  • /a1a/testAnt
  • /aaa/testAnt

不能匹配的路徑有

  • /testAnt
  • /aaaa/testAnt
  • /a/a/testAnt
  • /a?a/testAnt

即證明,?修飾的路徑,有且必須有一個字元代替?的位置,即只能匹配單個字元,且不能為/?這兩種特殊字元(因為/?在 url 路徑中比較特殊,除此之外其他單個字元均可),符合預期

2)*

後臺測試程式碼

//ant風格路徑
@RequestMapping("/a*a/testAnt")
public String testAnt() {
    return "success";
}

前臺測試程式碼

Ant風格路徑——*:<br/>
<a th:href="@{/requestMappingController/aa/testAnt}">測試ant風格路徑_/a*a/testAnt==>/aa/testAnt</a><br/>
<a th:href="@{/requestMappingController/a1a/testAnt}">測試ant風格路徑_/a*a/testAnt==>/a1a/testAnt</a><br/>
<a th:href="@{/requestMappingController/aaaaa/testAnt}">測試ant風格路徑_/a*a/testAnt==>/aaaaa/testAnt</a><br/>

測試結果

可以發現,/a*a/testAnt能夠匹配的路徑有

  • /aa/testAnt
  • /a1a/testAnt
  • /aaaaa/testAnt

即證明,*修飾的路徑,允許 0 個或多個字元代替*的位置,符合預期

3)**

上面說到,在使用**時,只能使用/**/xxx的方式,這裡對其進行驗證

後臺測試程式碼

//ant風格路徑
@RequestMapping("/a**a/testAnt")
public String testAnt() {
    return "success";
}

前臺測試程式碼

Ant風格路徑——**:<br/>
<a th:href="@{/requestMappingController/aa/testAnt}">測試ant風格路徑_/a**a/testAnt==>/aa/testAnt</a><br/>
<a th:href="@{/requestMappingController/a1a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a1a/testAnt</a><br/>
<a th:href="@{/requestMappingController/a1a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a11a/testAnt</a><br/>
<a th:href="@{/requestMappingController/a**a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a**a/testAnt</a><br/>
<a th:href="@{/requestMappingController/aaaaa/testAnt}">測試ant風格路徑_/a**a/testAnt==>/aaaaa/testAnt</a><br/>
<a th:href="@{/requestMappingController/a/a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a/a/testAnt</a><br/>
<a th:href="@{/requestMappingController/a/d/e/a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a/d/e/a/testAnt</a><br/>

測試結果

可以發現,/a**a/testAnt能夠匹配的路徑有

  • /aa/testAnt
  • /a1a/testAnt
  • /a11a/testAnt
  • /a**a/testAnt
  • /aaaaa/testAnt

不能匹配的路徑有

  • /a/a/testAnt
  • /a/d/e/a/testAnt

不符合預期

存疑點:這裡/a**a/多層路徑不能匹配,而 0 個或多個字元能夠匹配,這與課程中的“兩顆星真的就是兩顆星”不符,其匹配規則與/a*a/一致,即/a**a/ <==> /a*a/,兩顆星與一顆星作用相同,此點存疑

上述只是對**的錯誤用法時的匹配規則,下面才是真正對**的正確用法驗證,請看

後臺測試程式碼

//ant風格路徑
@RequestMapping("/**/testAnt")
public String testAnt() {
    return "success";
}

前臺測試程式碼

Ant風格路徑——**:<br/>
<a th:href="@{/requestMappingController/testAnt}">測試ant風格路徑_/a**a/testAnt==>/testAnt</a><br/>
<a th:href="@{/requestMappingController/a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a/testAnt</a><br/>
<a th:href="@{/requestMappingController/a/a/a/a/testAnt}">測試ant風格路徑_/a**a/testAnt==>/a/a/a/a/testAnt</a><br/>

測試結果

可以發現,不管中間新增多少層路徑都是能夠匹配成功的,符合預期

8、路徑中的佔位符

  • 原始方式:/deleteUser?id=1
  • rest 方式:/deleteuser/11

SpringMVC 路徑中的佔位符常用於 restful 風格中,當請求路徑中將某些資料通過路徑的方式傳輸到伺服器中,就可以在相應的@RequestMapping註解的value屬性中通過佔位符{xxx}表示傳輸的資料,再通過@PathVariable註解,將佔位符所表示的資料賦值給控制器方法的形參

無註解形參

  • 測試條件:①只使用{xxx}佔位符而不使用@PathVariable註解;②形參名稱與請求中的佔位符名稱同名
  • 測試目的:①請求能否匹配成功;②同名形參是否能夠接收到請求路徑中的佔位符

後臺測試程式碼

@RequestMapping("/testRest/{id}/{username}")
public String testRest(String id, String username) {
    System.out.println("id=" + id + ", username=" + username);
    return "success";
}

前臺測試程式碼

路徑中的佔位符:<br/>
<a th:href="@{/requestMappingController/testRest/1/admin}">測試路徑中的佔位符==>/testRest/1/admin</a><br/>

測試結果

後臺日誌

id=null, username=null

可以發現,請求能夠匹配成功,但是同名形參無法接收到佔位符的值

帶註解形參

檢視PathVariable註解原始碼

可以看到,它只能作用在方法引數上,那麼怎麼用就一目瞭然了

後臺測試程式碼

@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id") String id, @PathVariable("username") String username) {
    System.out.println("id=" + id + ", username=" + username);
    return "success";
}

測試結果

後臺日誌

id=1, username=admin

可以發現,請求能夠匹配成功,形參通過@PathVariable註解接收到了佔位符的值

不設定佔位符

<a th:href="@{/requestMappingController/testRest}">測試路徑中的佔位符==>/testRest</a><br/>

測試結果

可以看到,沒有佔位符時,直接顯示了404錯誤,即表示路徑中存在佔位符的控制器方法不能匹配未設定佔位符的請求

也就是說,路徑中存在佔位符的控制器方法,只能接收帶了對應占位符的請求

佔位符為空值或空格

<a th:href="@{/requestMappingController/testRest///}">測試路徑中的佔位符_空值==>/testRest///</a><br/>
<a th:href="@{/requestMappingController/testRest/ / /}">測試路徑中的佔位符_空格==>/testRest/ / /</a><br/>

測試結果

同時佔位符為空格的情況是,後臺列印了日誌:id= , username=

可以看到,

  • 空值匹配失敗,報了404錯誤
  • 空格匹配成功,路勁中對其解析成了對應的URL編碼,即%20

小結

由以上情況測試結果可以得出

  • SpringMVC 支援路徑中含有佔位符的形式
  • 佔位符只能通過@PathVariable註解獲取(就目前所學知識而言)
  • 佔位符可以匹配特殊字元——空格,但不能匹配空字元

總結

@RequestMapping註解

  • 功能:將請求和處理請求的控制器方法關聯起來,建立對映關係
  • 位置:作用在類上(請求路徑的初始資訊);作用在方法上(請求路徑的具體資訊)
  • value屬性:可以匹配多個請求路徑,匹配失敗報404
  • method屬性:支援GETPOSTPUTDELETE,預設不限制,匹配失敗報405
  • params屬性:四種方式,param!paramparam==valueparam!=value,匹配失敗報400
  • headers屬性:四種方式,header!headerheader==valueheader!=value,匹配失敗報400
  • 支援 Ant 風格路徑:?(單個字元)、*(0 或多個字元)和**(0 或多層路徑)
  • 支援路徑中的佔位符:{xxx}佔位符、@PathVariable賦值形參

以下導圖僅供參考