SpringMVC接口定義RequestMapping這些細節(jié)你用過嗎?
環(huán)境:Spring5.3.25
概述
你可以使用@RequestMapping注釋將請求映射到控制器(controller)方法。它有各種屬性,可以根據(jù)URL、HTTP方法、請求參數(shù)、頭和媒體類型進行匹配。你可以在類級別使用它來表示共享映射,或者在方法級別使用它來縮小到特定的端點映射。
還有HTTP方法特定的快捷方式變體@RequestMapping:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
提供的快捷方式是自定義注釋,因為大多數(shù)控制器方法應該映射到特定的HTTP方法,而不是使用@RequestMapping,默認情況下,匹配所有HTTP方法。在類級別上仍然需要@RequestMapping來表示共享映射,統(tǒng)一前綴。
下面的例子有類型級和方法級的映射:?
URI模式
@RequestMapping方法可以使用URL模式進行映射。有兩種選擇:
PathPattern - 一個與URL路徑匹配的預解析模式,也被預解析為PathContainer。設計為web使用,該解決方案有效地處理編碼和路徑參數(shù),并有效地匹配。
AntPathMatcher
PathPattern是web應用程序的推薦解決方案,也是Spring WebFlux中的唯一選擇。在5.3版本之前,AntPathMatcher是Spring MVC中的唯一選擇,并且一直是默認選項。然而,PathPattern可以在MVC配置中啟用。
PathPattern支持與AntPathMatcher相同的模式語法。此外,它還支持捕獲模式,例如{*spring},用于在路徑的末尾匹配0個或多個路徑段。PathPattern還限制使用**來匹配多個路徑段,這樣它只允許在模式的末尾使用。在為給定的請求選擇最佳匹配模式時,這消除了許多不明確的情況。完整的模式語法請參考PathPattern和AntPathMatcher。
一些示例模式:
"/resources/ima?e.png" -匹配路徑段中的一個字符
"/resources/*.png" -在路徑段中匹配零個或多個字符
"/resources/**" -匹配多個路徑段
"/projects/{project}/versions" -匹配路徑段并將其作為變量捕獲
"/projects/{project:[a-z]+}/versions" -用正則表達式匹配并捕獲變量
獲取的URI變量可以通過@PathVariable訪問。例如:
你可以在類和方法級別聲明URI變量,如下例所示:?
URI變量會自動轉(zhuǎn)換為適當?shù)念愋停蛘咭l(fā)TypeMismatchException異常。默認情況下支持簡單類型(int、long、Date等),你也可以注冊對任何其他數(shù)據(jù)類型的支持。請參閱類型轉(zhuǎn)換和DataBinder。
你可以顯式地命名URI變量(例如,@PathVariable("customId")),但是如果名稱相同,并且你的代碼是用調(diào)試信息或Java 8上的-parameters(用了該標記方法上的參數(shù)名稱就被記錄下來)編譯器標記編譯的,則可以省略該細節(jié)。
后綴匹配
從5.3開始,默認情況下Spring MVC不再執(zhí)行.*后綴模式匹配,其中映射到/person的控制器也隱式映射到/person.*。因此,路徑擴展不再用于解釋響應所請求的內(nèi)容類型——例如/person.pdf、/person.xml等等。
當瀏覽器用來發(fā)送難以一致解釋的Accept頭時,以這種方式使用文件擴展名是必要的。目前,這不再是必要的,使用Accept報頭應該是首選。
隨著時間的推移,文件擴展名的使用在許多方面都被證明是有問題的。當它與URI變量、路徑參數(shù)和URI編碼的使用重疊時,可能會導致歧義。關(guān)于基于url的授權(quán)和安全性的推理。
要在5.3之前的版本中完全禁用路徑擴展的使用,請設置如下:
useSuffixPatternMatching(false),參見PathMatchConfigurer
favorpatheextension(false),參見ContentNegotiationConfigurer
通過“Accept”頭以外的方式請求內(nèi)容類型仍然是有用的,例如在瀏覽器中輸入URL時。路徑擴展的安全替代方法是使用查詢參數(shù)策略。如果必須使用文件擴展名,請考慮通過ContentNegotiationConfigurer的mediaTypes屬性將它們限制為顯式注冊的擴展名列表。
Consumer媒體類型
你可以根據(jù)請求的Content-Type縮小請求映射,示例如下:?
consume屬性還支持否定表達式——例如,!text/plain表示除text/plain以外的任何內(nèi)容類型。
你可以在類級別聲明共享消費屬性。然而,與大多數(shù)其他請求映射屬性不同的是,當在類級使用時,方法級使用屬性重寫,而不是擴展類級聲明。
MediaType為常用的媒體類型提供常量,例如APPLICATION_JSON_VALUE和APPLICATION_XML_VALUE。
Producer媒體類型
你可以根據(jù)Accept請求頭和控制器方法產(chǎn)生的內(nèi)容類型列表來縮小請求映射,如下面的例子所示:?
媒體類型可以指定字符集。支持非表達式——例如,!text/plain表示除“text/plain”之外的任何內(nèi)容類型。
你可以在類級別聲明一個共享的produces屬性。然而,與大多數(shù)其他請求映射屬性不同的是,當在類級使用時,方法級產(chǎn)生屬性重寫,而不是擴展類級聲明。
請求參數(shù)與Header
可以根據(jù)請求參數(shù)條件縮小請求映射。你可以測試是否有請求參數(shù)(myParam),或者是否有特定的值(myParam=myValue)。下面的例子展示了如何測試一個特定的值:?
你也可以使用相同的請求頭條件,如下面的例子所示:?
HTTP請求Method
@GetMapping(和@RequestMapping(method=HttpMethod.GET))對請求映射透明地支持HTTP HEAD。控制器方法不需要改變。應用于javax.servlet.http中的響應包裝器。HttpServlet,確保Content-Length頭被設置為寫入的字節(jié)數(shù)(而不實際寫入響應)。
@GetMapping(和@RequestMapping(method=HttpMethod.GET))隱式映射到并支持HTTP HEAD。處理HTTP HEAD請求時就像處理HTTP GET一樣,不同的是,它不是寫入正文,而是計算字節(jié)數(shù),并設置Content-Length報頭。
默認情況下,HTTP OPTIONS是通過將Allow響應頭設置為所有具有匹配URL模式的@RequestMapping方法中列出的HTTP方法列表來處理的。
對于沒有HTTP方法聲明的@RequestMapping,允許頭被設置為GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS。控制器方法應該始終聲明支持的HTTP方法(例如,通過使用特定于HTTP方法的變量:@GetMapping、@PostMapping和其他)。
你可以顯式地將@RequestMapping方法映射到HTTP HEAD和HTTP OPTIONS,但在一般情況下這是不必要的。
自定義注解
Spring MVC支持對請求映射使用組合注釋。這些注釋本身是用@RequestMapping進行元注釋的,并且組合起來重新聲明@RequestMapping屬性的一個子集(或全部),目的更窄、更具體。
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping和@PatchMapping是組合注釋的例子。提供它們的原因是,大多數(shù)控制器方法都應該映射到特定的HTTP方法,而不是使用@RequestMapping,默認情況下,它匹配所有HTTP方法。如果需要一個組合注釋的示例,請查看它們是如何聲明的。
Spring MVC還支持使用自定義請求匹配邏輯的自定義請求映射屬性。這是一個更高級的選項,需要子類化RequestMappingHandlerMapping并覆蓋getCustomMethodCondition方法,在該方法中你可以檢查自定義屬性并返回自己的RequestCondition。
顯示的注冊
你可以以編程方式注冊處理程序方法,可以將其用于動態(tài)注冊或高級情況,例如不同url下相同處理程序的不同實例。下面的例子注冊了一個處理器方法:?
完畢!!!