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