SpringMvc之參數綁定注解詳解


  在 SpringMVC 中,提交請求的數據是通過方法形參來接收的。從客戶端請求的 key/value 數據,經過參數綁定,將 key/value 數據綁定到 Controller 的形參上,然后在 Controller 就可以直接使用該形參。

一、類型支持

  1、默認支持類型

  SpringMVC 有支持的默認參數類型,我們直接在形參上給出這些默認類型的聲明,就能直接使用了。

HttpServletRequest 對象

HttpServletResponse 對象

HttpSession 對象

Model/ModelMap 對象

@RequestMapping("/defaultParameter")
    public ModelAndView defaultParameter(HttpServletRequest request,HttpServletResponse response, HttpSession session,Model model,ModelMap modelMap) throws Exception{return null;
    }

  2、基本數據類型

1、byte,占用一個字節,取值范圍為 -128-127,默認是“\u0000”,表示空
2、short,占用兩個字節,取值范圍為 -32768-32767
3、int,占用四個字節,-2147483648-2147483647
4、long,占用八個字節,對 long 型變量賦值時必須加上"L"或“l”,否則不認為是 long5、float,占用四個字節,對 float 型進行賦值的時候必須加上“F”或“f”,如果不加,會產生編譯錯誤,因為系統自動將其定義為 double 型變量。double轉換為float類型數據會損失精度。
float a = 12.23產生編譯錯誤的,float a = 12是正確的 6、double,占用八個字節,對 double 型變量賦值的時候最好加上“D”或“d”,但加不加不是硬性規定 7、char,占用兩個字節,在定義字符型變量時,要用單引號括起來 8、boolean,只有兩個值“true”和“false”,默認值為false,不能用0或非0來代替,這點和C語言不同 
@RequestMapping(value = {"/card"}, method = RequestMethod.GET)
public TravelCard getTravelCard(@RequestParam("amount") long amount) {
    return null;
}

  3、包裝數據類型的綁定

  包裝類型如Integer、Long、Byte、Double、Float、Short,(String 類型在這也是適用的)。

  建議所有的參數都用包裝類型,別用原始類型,因為無法將null轉換為原始類型,入參不傳遞此參數時則會報錯。

@RequestMapping(value = {"/card"}, method = RequestMethod.GET)
public TravelCard getTravelCard(@RequestParam("amount") Integer amount) {
    return null;
}

  4、POJO(實體類)類型的綁定

@RequestMapping(value = {"/passenger"}, method = RequestMethod.POST)
public long insertOne(@RequestBody Passenger passenger) {
    LOGGER.info("Get a request for insertPassenger(POST).");
    return this.passengerService.insertOne(passenger);
}

二、@RequestMapping注解屬性

  RequestMapping是一個用來處理請求地址映射的注解,可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。RequestMapping注解有六個屬性,下面我們把她分成三類進行說明。

  1、value, method;  

  value:指定請求的實際地址,指定的地址可以是URI Template 模式(后面將會說明);當只設置value一個屬性時,value可以省略不寫,當有其他屬性時則需要加上進行區分。
  method:指定請求的method類型, GET、POST、PUT、DELETE等;

@RequestMapping("/v1/metro") public class PassengerController {
}

@RequestMapping(value = {"/travel"}, method = RequestMethod.POST) public Map travel(@RequestParam long passengerId,
                   @RequestParam long startStation,
                   @RequestParam long endStation,
                   @RequestParam int cardType) {return null;
}

  value的uri值為以下三類:

    A) 可以指定為普通的具體值;

    B)  可以指定為含有某變量的一類值(URI Template Patterns with Path Variables);

    C) 可以指定為含正則表達式的一類值( URI Template Patterns with Regular Expressions);

    example B)

@RequestMapping(value = {"/travel/{passengerId}"}, method = RequestMethod.GET)
public List<TravelRecord> queryTravelRecords(@PathVariable("passengerId") long passengerId) {return null;
}

    example C)

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\d\.\d\.\d}.{extension:\.[a-z]}")  
public void handle(@PathVariable String version, @PathVariable String extension) {      
    // ...   
}

  2、consumes,produces;

  consumes:指定處理請求的提交內容類型(Content-Type),例如application/json, text/html;

@Controller  
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")  
public void addPet(@RequestBody Pet pet, Model model) {      
    // implementation omitted  
}  

  方法僅處理request的Content-Type為“application/json”類型的請求。

  produces:指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;

@Controller  
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")  
@ResponseBody  
public Pet getPet(@PathVariable String petId, Model model) {      
    // implementation omitted  
}

  方法僅處理request請求中Accept頭中包含了"application/json"的請求,同時暗示了返回的內容類型為application/json;

  3、params,headers;

  params:指定request中必須包含某些參數值是,才讓該方法處理。

@Controller  
@RequestMapping("/owners/{ownerId}")  
public class RelativePathUriTemplateController {  
  
  @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")  
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {      
    // implementation omitted  
  }  
}

  僅處理請求中包含了名為“myParam”,值為“myValue”的請求;

  headers:指定request中必須包含某些指定的header值,才能讓該方法處理請求。

@Controller  
@RequestMapping("/owners/{ownerId}")  
public class RelativePathUriTemplateController {  
  
@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="Referer=http://www.ifeng.com/")  
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {      
    // implementation omitted  
  }  
}

  僅處理request的header中包含了指定“Refer”請求頭和對應值為“http://www.ifeng.com/”的請求;

三、參數綁定

  handler method 參數綁定常用的注解,我們根據他們處理的Request的不同內容部分分為四類:(主要講解常用類型)

  A、處理requet uri 部分(這里指uri template中variable,不含queryString部分)的注解:   @PathVariable;

  B、處理request header部分的注解:   @RequestHeader, @CookieValue;

  C、處理request body部分的注解:@RequestParam,  @RequestBody;

  D、處理attribute類型是注解: @SessionAttributes, @ModelAttribute;

  1、 @PathVariable

  當使用@RequestMapping URI template 樣式映射時, 即 someUrl/{paramId}, 這時的paramId可通過 @Pathvariable注解綁定它傳過來的值到方法的參數上。

@RequestMapping(value = {"/travel/{passengerId}"}, method = RequestMethod.GET)
public List<TravelRecord> queryTravelRecords(@PathVariable("passengerId") long passengerId) {
    return null;
}

  若方法參數名稱和需要綁定的uri template中變量名稱不一致,需要在@PathVariable("name")指定uri template中的名稱。

  2、 @RequestHeader、@CookieValue

  @RequestHeader 注解,可以把Request請求header部分的值綁定到方法的參數上。

  一個Request 的header部分:

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  
@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive)  {  
  //...  
  
} 

  @CookieValue 可以把Request header中關於cookie的值綁定到方法的參數上。

  有如下Cookie值:

@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
  //...  
} 

  3、@RequestParam, @RequestBody

  @RequestParam
  A) 常用來處理簡單類型的綁定,通過Request.getParameter() 獲取的String可直接轉換為簡單類型的情況( String--> 簡單類型的轉換操作由ConversionService配置的轉換器來完成);因為使用request.getParameter()方式獲取參數,所以可以處理get 方式中queryString的值,也可以處理post方式中 body data的值;
  B)用來處理Content-Type: 為 application/x-www-form-urlencoded編碼的內容,提交方式GET、POST;
  C) 該注解有3個屬性: value、required、defaultValue; value用來指定要傳入值的id名稱(改變參數名字),required用來指示參數是否必須綁定,defaultValue用於對參數設置默認值,required為true時,如果參數為空,會報錯,但是當required=true,和defaultValue= 同時出現時,required失效,可傳可不傳;

@RequestMapping(value = {"/travel"}, method = RequestMethod.POST)
public Map travel(@RequestParam(defaultValue = 1) long passengerId, @RequestParam long startStation, @RequestParam long endStation, @RequestParam(value="card") int cardType) {
    return null;
}

  @RequestBody
  該注解常用來處理Content-Type: 不是application/x-www-form-urlencoded編碼的內容,例如application/json, application/xml等;
  它是通過使用HandlerAdapter 配置的HttpMessageConverters來解析post data body,然后綁定到相應的bean上的。
  因為配置有FormHttpMessageConverter,所以也可以用來處理 application/x-www-form-urlencoded的內容,處理完的結果放在一個MultiValueMap<String, String>里,這種情況在某些特殊需求下使用,詳情查看FormHttpMessageConverter api;

@RequestMapping(value = "/something", method = RequestMethod.PUT)  
public void handle(@RequestBody String body, Writer writer) throws IOException {  
  writer.write(body);  
} 

  因為@RequestBody是將post請求中content值轉為一個整體對象。@RequestBody的解析有兩個條件:
  1. POST請求中content的值必須為json格式(存儲形式可以是字符串,也可以是byte數組);
  2. @RequestBody注解的參數類型必須是完全可以接收參數值的類型,比如:Map,JSONObject,或者對應的JavaBean;所以Integer等類型不能作為@RequestBody注解的參數類型。

  4、@SessionAttributes, @ModelAttribute

  @SessionAttributes:
  該注解用來綁定HttpSession中的attribute對象的值,便於在方法中的參數里使用。
  該注解有value、types兩個屬性,可以通過名字和類型指定要使用的attribute 對象;

@Controller  
@RequestMapping("/editPet.do")  
@SessionAttributes("pet")  
public class EditPetForm {  
    // ...  
}  

  @ModelAttribute
  該注解有兩個用法,一個是用於方法上,一個是用於參數上;
  用於方法上時: 通常用來在處理@RequestMapping之前,為請求綁定需要從后台查詢的model;
  用於參數上時: 用來通過名稱對應,把相應名稱的值綁定到注解的參數bean上;要綁定的值來源於:
    A) @SessionAttributes 啟用的attribute 對象上;
    B) @ModelAttribute 用於方法上時指定的model對象;
    C) 上述兩種情況都沒有時,new一個需要綁定的bean對象,然后把request中按名稱對應的方式把值綁定到bean中。

  用到方法上@ModelAttribute的示例代碼:

// 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);  
}  

  這種方式實際的效果就是在調用@RequestMapping的方法之前,為request對象的model里put(“account”, Account);
  用在參數上的@ModelAttribute示例代碼:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)  
public String processSubmit(@ModelAttribute Pet pet) {  
}

  首先查詢 @SessionAttributes有無綁定的Pet對象,若沒有則查詢@ModelAttribute方法層面上是否綁定了Pet對象,若沒有則將URI template中的值按對應的名稱綁定到Pet對象的各屬性上。

四、RequestBody、ResponseBody比較

  @RequestBody
  作用:
    i) 該注解用於讀取Request請求的body部分數據,使用系統默認配置的HttpMessageConverter進行解析,然后把相應的數據綁定到要返回的對象上;
    ii) 再把HttpMessageConverter返回的對象數據綁定到 controller中方法的參數上。
  使用時機:
    A) GET、POST方式提時, 根據request header Content-Type的值來判斷:
      application/x-www-form-urlencoded, 可選(即非必須,因為這種情況的數據@RequestParam, @ModelAttribute也可以處理,當然@RequestBody也能處理);
      multipart/form-data, 不能處理(即使用@RequestBody不能處理這種格式的數據);
      其他格式, 必須(其他格式包括application/json, application/xml等。這些格式的數據,必須使用@RequestBody來處理);
    B) PUT方式提交時, 根據request header Content-Type的值來判斷:
      application/x-www-form-urlencoded, 必須;
      multipart/form-data, 不能處理;
      其他格式, 必須;
  說明:request的body部分的數據編碼格式由header部分的Content-Type指定;

  @ResponseBody
  作用:
    該注解用於將Controller的方法返回的對象,通過適當的HttpMessageConverter轉換為指定格式后,寫入到Response對象的body數據區。
  使用時機:
    返回的數據不是html標簽的頁面,而是其他某種格式的數據時(如json、xml等)使用;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM