SpringMVC常用注解

Spring的模型-視圖-控制器(MVC)框架是圍繞一個DispatcherServlet來設計的,這個Servlet會把請求分發給各個處理器,并支持可配置的處理器映射、

視圖渲染、本地化、時區與主題渲染等,甚至還能支持文件上傳。處理器是你的應用中注解了@Controller和@RequestMapping的類和方法,

Spring為處理器方法提供了極其多樣靈活的配置。Spring 3.0以后提供了@Controller注解機制、@PathVariable注解以及一些其他的特性,

你可以使用它們來進行RESTful web站點和應用的開發。

在Spring Web MVC中,你可以使用任何對象來作為命令對象或表單返回對象,而無須實現一個框架相關的接口或基類。Spring的數據綁定非常靈活:比如,

它會把數據類型不匹配當成可由應用自行處理的運行時驗證錯誤,而非系統錯誤。你可能會為了避免非法的類型轉換在表單對象中使用字符串來存儲數據,

但無類型的字符串無法描述業務數據的真正含義,并且你還需要把它們轉換成對應的業務對象類型。有了Spring的驗證機制,意味著你再也不需這么做了,

并且直接將業務對象綁定到表單對象上通常是更好的選擇。

Spring的視圖解析也是設計得異常靈活。控制器一般負責準備一個Map模型、填充數據、返回一個合適的視圖名等,同時它也可以直接將數據寫到響應流中。

視圖名的解析高度靈活,支持多種配置,包括通過文件擴展名、Accept內容頭、bean、配置文件等的配置,甚至你還可以自己實現一個視圖解析器ViewResolver。

模型(MVC中的M,model)其實是一個Map類型的接口,徹底地把數據從視圖技術中抽象分離了出來。你可以與基于模板的渲染技術直接整合,

如JSP、Velocity和Freemarker等,或者你還可以直接生成XML、JSON、Atom以及其他多種類型的內容。Map模型會簡單地被轉換成合適的格式,

比如JSP的請求屬性(attribute),一個Velocity模板的模型等。

1 @Controller

@Controller注解可以認為是被標注類的原型(stereotype),表明了這個類所承擔的角色。

分派器(DispatcherServlet)會掃描所有注解了@Controller的類,檢測其中通過@RequestMapping注解配置的方法

2 @RequestMapping

你可以使用@RequestMapping注解來將請求URL,如/appointments等,映射到整個類上或某個特定的處理器方法上。一般來說,

類級別的注解負責將一個特定(或符合某種模式)的請求路徑映射到一個控制器上,

同時通過方法級別的注解來細化映射,即根據特定的HTTP請求方法(“GET”“POST”方法等)、HTTP請求中是否攜帶特定參數等條件,將請求映射到匹配的方法上。

例如:

@Controller

@RequestMapping("/appointments")

public class AppointmentsController {

private final AppointmentBook appointmentBook;

@Autowired

public AppointmentsController(AppointmentBook appointmentBook) {

this.appointmentBook = appointmentBook;

}

@RequestMapping(method = RequestMethod.GET)

public Map get() {

return appointmentBook.getAppointmentsForToday();

}

@RequestMapping(path = "/{day}", method = RequestMethod.GET)

public Map getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {

return appointmentBook.getAppointmentsForDay(day);

}

@RequestMapping(path = "/new", method = RequestMethod.GET)

public AppointmentForm getNewForm() {

return new AppointmentForm();

}

@RequestMapping(method = RequestMethod.POST)

public String add(@Valid AppointmentForm appointment, BindingResult result) {

if (result.hasErrors()) {

return "appointments/new";

}

appointmentBook.addAppointment(appointment);

return "redirect:/appointments";

}

}

在上面的示例中,許多地方都使用到了@RequestMapping注解。第一次使用點是作用于類級別的,它指示了所有/appointments開頭的路徑都會被映射到控制器下。

get()方法上的@RequestMapping注解對請求路徑進行了進一步細化:它僅接受GET方法的請求。這樣,一個請求路徑為/appointments、HTTP方法為GET的請求,

將會最終進入到這個方法被處理。add()方法也做了類似的細化,而getNewForm()方法則同時注解了能夠接受的請求的HTTP方法和路徑。這種情況下,

一個路徑為appointments/new、HTTP方法為GET的請求將會被這個方法所處理。getForDay()方法則展示了使用@RequestMapping注解的另一個技巧:URI模板。

2.1 URI模板

URI模板是一個類似于URI的字符串,只不過其中包含了一個或多個的變量名。當你使用實際的值去填充這些變量名的時候,模板就退化成了一個URI。

在URI模板的RFC提議中定義了一個URI是如何進行參數化的。比如說,一個這個URI模板http://www.example.com/users/{userId}就包含了一個變量名userId。

將值fred賦給這個變量名后,它就變成了一個URI:http://www.example.com/users/fred

2.2 @PathVariable

在Spring MVC中你可以在方法參數上使用@PathVariable注解,將其與URI模板中的參數綁定起來:

@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)

public String findOwner(@PathVariable String ownerId, Model model) {

Owner owner = ownerService.findOwner(ownerId);

model.addAttribute("owner", owner);

return "displayOwner";

}

URI模板"/owners/{ownerId}"指定了一個變量,名為ownerId。當控制器處理這個請求的時候,ownerId的值就會被URI模板中對應部分的值所填充。

比如說,如果請求的URI是/owners/fred,此時變量ownerId的值就是fred.

2.2.1 為了處理@PathVariables注解,Spring MVC必須通過變量名來找到URI模板中相對應的變量。你可以在注解中直接聲明:

@RequestMapping(path="/owners/{ownerId}}", method=RequestMethod.GET)

public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {

// 具體的方法代碼…

}

或者,如果URI模板中的變量名與方法的參數名是相同的,則你可以不必再指定一次。只要你在編譯的時候留下debug信息,Spring MVC就可以自動匹配URL模板中與方法參數名相同的變量名。

@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)

public String findOwner(@PathVariable String ownerId, Model model) {

// 具體的方法代碼…

}

2.2.2 一個方法可以擁有任意數量的@PathVariable注解:

@RequestMapping(path="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)

public String findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {

Owner owner = ownerService.findOwner(ownerId);

Pet pet = owner.getPet(petId);

model.addAttribute("pet", pet);

return "displayPet";

}

2.2.3 URI模板可以從類級別和方法級別的 @RequestMapping 注解獲取數據。因此,像這樣的findPet()方法可以被類似于/owners/42/pets/21這樣的URL路由并調用到:

@Controller

@RequestMapping("/owners/{ownerId}")

public class RelativePathUriTemplateController {

@RequestMapping("/pets/{petId}")

public void findPet(@PathVariable_String ownerId, @PathVariable String petId, Model model) {

// 方法實現體這里忽略

}

}

2.3 帶正則表達式的URI模板

有時候你可能需要更準確地描述一個URI模板的變量,比如說這個URL:"/spring-web/spring-web-3.0.5.jar。你要怎么把它分解成幾個有意義的部分呢?

@RequestMapping注解支持你在URI模板變量中使用正則表達式。語法是{varName:regex},其中第一部分定義了變量名,第二部分就是你所要應用的正則表達式。比如下面的代碼樣例:

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")

public void handle(@PathVariable String version, @PathVariable String extension) {

// 代碼部分省略...

}

}

2.4 Path Patterns

除了URI模板外,@RequestMapping注解還支持Ant風格的路徑模式(如/myPath/*.do等)。不僅如此,還可以把URI模板變量和Ant風格

的glob組合起來使用(比如/owners/*/pets/{petId}這樣的用法等)。

2.5 路徑樣式的匹配(Path Pattern Comparison)

2.5.1 當一個URL同時匹配多個模板(pattern)時,我們將需要一個算法來決定其中最匹配的一個。

2.5.2 URI模板變量的數目和通配符數量的總和最少的那個路徑模板更準確。舉個例子,/hotels/{hotel}/*這個路徑擁有一個URI變量和一個通配符,

而/hotels/{hotel}/**這個路徑則擁有一個URI變量和兩個通配符,因此,我們認為前者是更準確的路徑模板。

2.5.3 如果兩個模板的URI模板數量和通配符數量總和一致,則路徑更長的那個模板更準確。舉個例子,/foo/bar*就被認為比/foo/*更準確,因為前者的路徑更長。

2.5.4 如果兩個模板的數量和長度均一致,則那個具有更少通配符的模板是更加準確的。比如,/hotels/{hotel}就比/hotels/*更精確。

2.5.5 默認的通配模式/**比其他所有的模式都更“不準確”。比方說,/api/{a}/{b}/{c}就比默認的通配模式/**要更準確

2.5.6 前綴通配(比如/public/**)被認為比其他任何不包括雙通配符的模式更不準確。比如說,/public/path3/{a}/{b}/{c}就比/public/**更準確

2.6 帶占位符的路徑模式(path patterns)

@RequestMapping注解支持在路徑中使用占位符,以取得一些本地配置、系統配置、環境變量等。這個特性有時很有用,比如說控制器的映射路徑需要通過配置來定制的場景。

如果想了解更多關于占位符的信息,可以參考PropertyPlaceholderConfigurer這個類的文檔。

2.7 后綴模式匹配(Suffix Pattern Matching)

Spring MVC默認采用".*"的后綴模式匹配來進行路徑匹配,因此,一個映射到/person路徑的控制器也會隱式地被映射到/person.*。

這使得通過URL來請求同一資源文件的不同格式變得更簡單(比如/person.pdf,/person.xml)。

你可以關閉默認的后綴模式匹配,或者顯式地將路徑后綴限定到一些特定格式上for content negotiation purpose。我們推薦這樣做,

這樣可以減少映射請求時可以帶來的一些二義性,比如請求以下路徑/person/{id}時,路徑中的點號后面帶的可能不是描述內容格式,

比如/person/joe@email.com vs /person/joe@email.com.json。而且正如下面馬上要提到的,后綴模式通配以及內容協商有時可能會被黑客用來進行攻擊,

因此,對后綴通配進行有意義的限定是有好處的。

2.8 矩陣變量

使用 @MatrixVariable 注解

2.8.1 原來的URI規范RFC 3986中允許在路徑段落中攜帶鍵值對,但規范沒有明確給這樣的鍵值對定義術語。有人叫“URI路徑參數”,也有叫“矩陣URI”的。

后者是Tim Berners-Lee首先在其博客中提到的術語,被使用得要更加頻繁一些,知名度也更高些。而在Spring MVC中,我們稱這樣的鍵值對為矩陣變量。

// GET /owners/42;q=11/pets/21;q=22

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)

public void findPet(

@MatrixVariable(name="q", pathVar="ownerId") int q1,

@MatrixVariable(name="q", pathVar="petId") int q2) {

// q1 == 11

// q2 == 22

}

2.8.2 如果要允許矩陣變量的使用,你必須把RequestMappingHandlerMapping類的removeSemicolonContent屬性設置為false。該值默認是true的。

MVC的Java編程配置和命名空間配置都提供了啟用矩陣變量的方式。

如果你是使用Java編程的方式,“MVC Java高級定制化配置”一節描述了如何對RequestMappingHandlerMapping進行定制。

而使用MVC的命名空間配置時,你可以把元素下的enable-matrix-variables屬性設置為true。該值默認情況下是配置為false的。

2.9 可消費的媒體類型

你可以指定一組可消費的媒體類型,縮小映射的范圍。這樣只有當請求頭中 Content-Type 的值與指定可消費的媒體類型中有相同的時候,請求才會被匹配。比如下面這個例子:

@Controller

@RequestMapping(path = "/pets", method = RequestMethod.POST, consumes="application/json")

public void addPet(@RequestBody Pet pet, Model model) {

// 方法實現省略

}

指定可消費媒體類型的表達式中還可以使用否定,比如,可以使用 !text/plain 來匹配所有請求頭 Content-Type 中不含 text/plain 的請求。

同時,在MediaType類中還定義了一些常量,比如APPLICATION_JSON_VALUE、APPLICATION_JSON_UTF8_VALUE等,推薦更多地使用它們。

@Controller

@RequestMapping(path = "/pets", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)

public void addPet(@RequestBody Pet pet, Model model) {

// 方法實現省略

}

consumes 屬性提供的是方法級的類型支持。與其他屬性不同,當在類型級使用時,方法級的消費類型將覆蓋類型級的配置,而非繼承關系。

2.10 可生產的媒體類型

你可以指定一組可生產的媒體類型,縮小映射的范圍。這樣只有當請求頭中 Accept 的值與指定可生產的媒體類型中有相同的時候,請求才會被匹配。

而且,使用 produces 條件可以確保用于生成響應(response)的內容與指定的可生產的媒體類型是相同的。舉個例子:

@Controller

@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)

@ResponseBody

public Pet getPet(@PathVariable String petId, Model model) {

// 方法實現省略

}

produces 屬性提供的是方法級的類型支持。與其他屬性不同,當在類型級使用時,方法級的消費類型將覆蓋類型級的配置,而非繼承關系。

2.11 請求參數與請求頭的值

你可以篩選請求參數的條件來縮小請求匹配范圍,比如"myParam"、"!myParam"及"myParam=myValue"等。前兩個條件用于篩選存在/不存在某些請求參數的請求,

第三個條件篩選具有特定參數值的請求。下面有個例子,展示了如何使用請求參數值的篩選條件:

@Controller

@RequestMapping("/owners/{ownerId}")

public class RelativePathUriTemplateController {

@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")

public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {

// 實際實現省略

}

}

同樣,你可以用相同的條件來篩選請求頭的出現與否,或者篩選出一個具有特定值的請求頭:

@Controller

@RequestMapping("/owners/{ownerId}")

public class RelativePathUriTemplateController {

@RequestMapping(path = "/pets", method = RequestMethod.GET, headers="myHeader=myValue")

public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {

// 方法體實現省略

}

}

3 定義@RequestMapping注解的處理方法(handler method)

3.1 使用@RequestParam將請求參數綁定至方法參數

@Controller

@RequestMapping("/pets")

@SessionAttributes("pet")

public class EditPetForm {

// ...

@RequestMapping(method = RequestMapping.GET)

public String setupForm(@RequestParam("petId") int petId, ModelMap model) {

Pet pet = this.clinic.loadPet(petId);

model.addAttribute("pet", pet);

return "petForm";

}

// ,..

}

若參數使用了該注解,則該參數默認是必須提供的,但你也可以把該參數標注為非必須的:只需要將@RequestParam注解的required屬性設置為false即可(比如,@RequestParam(path="id", required=false))。

若所注解的方法參數類型不是String,則類型轉換會自動地發生。詳見"方法參數與類型轉換"一節

若@RequestParam注解的參數類型是Map或者MultiValueMap,則該Map中會自動填充所有的請求參數。

3.2 使用@RequestBody注解映射請求體

方法參數中的@RequestBody注解暗示了方法參數應該被綁定了HTTP請求體的值。舉個例子:

@RequestMapping(path = "/something", method = RequestMethod.PUT)

public void handle(@RequestBody String body, Writer writer) throws IOException {

writer.write(body);

}

3.3 使用@ResponseBody注解映射響應體

@ResponseBody注解與@RequestBody注解類似。@ResponseBody注解可被應用于方法上,標志該方法的返回值應該被直接寫回到HTTP響應體中去(而不會被被放置到Model中或被解釋為一個視圖名)。舉個例子:

@RequestMapping(path = "/something", method = RequestMethod.PUT)

@ResponseBody

public String helloWorld() {

return "Hello World"

}

上面的代碼結果是文本Hello World將被寫入HTTP的響應流中。

與@RequestBody注解類似,Spring使用了一個HttpMessageConverter來將返回對象轉換到響應體中。

3.4 使用@RestController注解創建REST控制器

當今讓控制器實現一個REST API是非常常見的,這種場景下控制器只需要提供JSON、XML或其他自定義的媒體類型內容即可。

你不需要在每個@RequestMapping方法上都增加一個@ResponseBody注解,更簡明的做法是,給你的控制器加上一個@RestController的注解。

@RestController是一個原生內置的注解,它結合了@ResponseBody與@Controller注解的功能。

3.5 對方法使用@ModelAttribute注解

@ModelAttribute注解可被應用在方法或方法參數上

3.5.1 被注解于方法上時的用法

注解在方法上的@ModelAttribute說明了方法的作用是用于添加一個或多個屬性到model上。這樣的方法能接受與@RequestMapping注解相同的參數類型,

只不過不能直接被映射到具體的請求上。在同一個控制器中,注解了@ModelAttribute的方法實際上會在@RequestMapping方法之前被調用。以下是幾個例子:

// Add one attribute

// The return value of the method is added to the model under the name "account"

// You can customize the name via @ModelAttribute("myAccount")

@ModelAttribute

public Account addAccount(@RequestParam String number) {

return accountManager.findAccount(number);

}

// Add multiple attributes

@ModelAttribute

public void populateModel(@RequestParam String number, Model model) {

model.addAttribute(accountManager.findAccount(number));

// add more ...

}

@ModelAttribute方法通常被用來填充一些公共需要的屬性或數據,比如一個下拉列表所預設的幾種狀態,或者寵物的幾種類型,或者去取得一個HTML表單渲染所需要的命令對象,比如Account等。

留意@ModelAttribute方法的兩種風格。在第一種寫法中,方法通過返回值的方式默認地將添加一個屬性;在第二種寫法中,方法接收一個Model對象,

然后可以向其中添加任意數量的屬性。你可以在根據需要,在兩種風格中選擇合適的一種。

一個控制器可以擁有數量不限的@ModelAttribute方法。同個控制器內的所有這些方法,都會在@RequestMapping方法之前被調用。

@ModelAttribute方法也可以定義在@ControllerAdvice注解的類中,并且這些@ModelAttribute可以同時對許多控制器生效。具體的信息可以參考使用@ControllerAdvice輔助控制器。

屬性名沒有被顯式指定的時候又當如何呢?在這種情況下,框架將根據屬性的類型給予一個默認名稱。舉個例子,若方法返回一個Account類型的對象,

則默認的屬性名為"account"。你可以通過設置@ModelAttribute注解的值來改變默認值。當向Model中直接添加屬性時,請使用合適的重載方法addAttribute(..)-即,帶或不帶屬性名的方法。

@ModelAttribute注解也可以被用在@RequestMapping方法上。這種情況下,@RequestMapping方法的返回值將會被解釋為model的一個屬性,而非一個視圖名

3.5.2 在方法參數上使用@ModelAttribute注解

注解在方法參數上的@ModelAttribute說明了該方法參數的值將由model中取得。如果model中找不到,那么該參數會先被實例化,然后被添加到model中。

在model中存在以后,請求中所有名稱匹配的參數都會填充到該參數中。這在Spring MVC中被稱為數據綁定,一個非常有用的特性,節約了你每次都需要手動從表格數據中轉換這些字段數據的時間。

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)

public String processSubmit(@ModelAttribute Pet pet) { }

以上面的代碼為例,這個Pet類型的實例可能來自哪里呢?有幾種可能:

它可能因為@SessionAttributes注解的使用已經存在于model中——詳見"在請求之間使用@SessionAttributes注解,使用HTTP會話保存模型數據"一節

它可能因為在同個控制器中使用了@ModelAttribute方法已經存在于model中——正如上一小節所敘述的

它可能是由URI模板變量和類型轉換中取得的(下面會詳細講解)

它可能是調用了自身的默認構造器被實例化出來的

@ModelAttribute方法常用于從數據庫中取一個屬性值,該值可能通過@SessionAttributes注解在請求中間傳遞。在一些情況下,使用URI模板變量和類型轉換的方式來取得一個屬性是更方便的方式。這里有個例子:

@RequestMapping(path = "/accounts/{account}", method = RequestMethod.PUT)

public String save(@ModelAttribute("account") Account account) {

}

上面這個例子中,model屬性的名稱("account")與URI模板變量的名稱相匹配。如果你配置了一個可以將String類型的賬戶值轉換成Account類型實例的轉換器Converter,那么上面這段代碼就可以工作的很好,而不需要再額外寫一個@ModelAttribute方法。

下一步就是數據的綁定。WebDataBinder類能將請求參數——包括字符串的查詢參數和表單字段等——通過名稱匹配到model的屬性上。

成功匹配的字段在需要的時候會進行一次類型轉換(從String類型到目標字段的類型),然后被填充到model對應的屬性中。

如何在控制器層來定制數據綁定的過程,在這一節 "定制WebDataBinder的初始化"中提及。

進行了數據綁定后,則可能會出現一些錯誤,比如沒有提供必須的字段、類型轉換過程的錯誤等。若想檢查這些錯誤,

可以在注解了@ModelAttribute的參數緊跟著聲明一個BindingResult參數:

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)

public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {

if (result.hasErrors()) {

return "petForm";

}

// ...

}

拿到BindingResult參數后,你可以檢查是否有錯誤。有時你可以通過Spring的表單標簽來在同一個表單上顯示錯誤信息。

BindingResult被用于記錄數據綁定過程的錯誤,因此除了數據綁定外,你還可以把該對象傳給自己定制的驗證器來調用驗證。

這使得數據綁定過程和驗證過程出現的錯誤可以被搜集到一處,然后一并返回給用戶:

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)

public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {

new PetValidator().validate(pet, result);

if (result.hasErrors()) {

return "petForm";

}

// ...

}

又或者,你可以通過添加一個JSR-303規范的@Valid注解,這樣驗證器會自動被調用。

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)

public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) {

if (result.hasErrors()) {

return "petForm";

}

// ...

}

3.6 使用@SessionAttributes注解,使用HTTP會話保存模型數據

類型級別的@SessionAttributes注解聲明了某個特定處理器所使用的會話屬性。通常它會列出該類型希望存儲到session或converstaion中的model屬性名或model的類型名,一般是用于在請求之間保存一些表單數據的bean。

以下的代碼段演示了該注解的用法,它指定了模型屬性的名稱

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

public class EditPetForm {

// ...

}

3.7 使用"application/x-www-form-urlencoded"數據

對于不是使用的瀏覽器的客戶端,我們也推薦使用這個注解來處理請求。但當請求是一個HTTP PUT方法的請求時,有一個事情需要注意。

瀏覽器可以通過HTTP的GET方法或POST方法來提交表單數據,非瀏覽器的客戶端還可以通過HTTP的PUT方法來提交表單。這就設計是個挑戰,

因為在Servlet規范中明確規定,ServletRequest.getParameter*()系列的方法只能支持通過HTTP POST方法的方式提交表單,而不支持HTTP PUT的方式。

為了支持HTTP的PUT類型和PATCH類型的請求,Spring的spring-web模塊提供了一個過濾器HttpPutFormContentFilter。你可以在web.xml文件中配置它:

httpPutFormFilter

org.springframework.web.filter.HttpPutFormContentFilter

httpPutFormFilter

dispatcherServlet

dispatcherServlet

org.springframework.web.servlet.DispatcherServlet

上面的過濾器將會攔截內容類型(content type)為application/x-www-form-urlencoded、HTTP方法為PUT或PATCH類型的請求,然后從請求體中讀取表單數據,

把它們包裝在ServletRequest中。這是為了使表單數據能夠通過ServletRequest.getParameter*()系列的方法來拿到。

因為HttpPutFormContentFilter會消費請求體的內容,因此,它不應該用于處理那些依賴于其他application/x-www-form-urlencoded轉換器的PUT和PATCH請求,

這包括了@RequestBodyMultiValueMap和HttpEntity>。

3.8 使用@CookieValue注解映射cookie值

@CookieValue注解能將一個方法參數與一個HTTP cookie的值進行綁定。

看一個這樣的場景:以下的這個cookie存儲在一個HTTP請求中:

JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

下面的代碼演示了拿到JSESSIONID這個cookie值的方法:

@RequestMapping("/displayHeaderInfo.do")

public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {

//...

}

若注解的目標方法參數不是String類型,則類型轉換會自動進行。

這個注解可以注解到處理器方法上,在Servlet環境和Portlet環境都能使用。

3.9 使用@RequestHeader注解映射請求頭屬性

@RequestHeader注解能將一個方法參數與一個請求頭屬性進行綁定。

以下是一個請求頭的例子:

Host ? ? ? ? ? ? ? ? ? ?localhost:8080

Accept ? ? ? ? ? ? ? ? ?text/html,application/xhtml+xml,application/xml;q=0.9

Accept-Language ? ? ? ? fr,en-gb;q=0.7,en;q=0.3

Accept-Encoding ? ? ? ? gzip,deflate

Accept-Charset ? ? ? ? ?ISO-8859-1,utf-8;q=0.7,*;q=0.7

Keep-Alive ? ? ? ? ? ? ?300

以下的代碼片段展示了如何取得Accept-Encoding請求頭和Keep-Alive請求頭的值:

@RequestMapping("/displayHeaderInfo.do")

public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,

@RequestHeader("Keep-Alive") long keepAlive) {

//...

}

參考文檔:http://7xvpsh.com1.z0.glb.clouddn.com/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容