天天看點

springmvc怎麼解析post_SpringMVC 參數綁定注解解析

本文介紹了用于參數綁定的相關注解。

綁定:将請求中的字段按照名字比對的原則填入模型對象。

SpringMVC就跟Struts2一樣,通過攔截器進行參數比對。

URI模闆變量

這裡指uri template中variable(路徑變量),不含queryString部分

@PathVariable

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

示例代碼:

@RestController

@RequestMapping("/users")

public class UserAction {

@GetMapping("/{id}")

public Result getUser(@PathVariable int id) {

return ResultUtil.successResult("123456");

}

}

上面代碼把URI template 中變量 ownerId的值和petId的值,綁定到方法的參數上。若方法參數名稱和需要綁定的uri template中變量名稱不一緻,需要在@PathVariable("name")指定uri template中的名稱。

請求頭

@RequestHeader

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

示例代碼:

這是一個Request 的header部分:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Encoding:gzip, deflate, br

Accept-Language:zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

Cache-Control:max-age=0

Connection:keep-alive

Host:localhost:8080

Upgrade-Insecure-Requests:1

User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36

@GetMapping("/getRequestHeader")

public Result getRequestHeader(@RequestHeader("Accept-Encoding") String encoding) {

return ResultUtil.successResult(encoding);

}

上面的代碼,把request header部分的 Accept-Encoding的值,綁定到參數encoding上。

@CookieValue

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

例如有如下Cookie值:

JSESSIONID=588DC770E582A3189B7E6210102EAE02

參數綁定的代碼:

@RequestMapping("/getCookie")

public Result getCookie(@CookieValue("JSESSIONID") String cookie) {

return ResultUtil.successResult(cookie);

}

即把JSESSIONID的值綁定到參數cookie上。

請求體

@RequestParam

常用來處理簡單類型的綁定,通過Request.getParameter() 擷取的String可直接轉換為簡單類型的情況( String--> 簡單類型的轉換操作由ConversionService配置的轉換器來完成);因為使用request.getParameter()方式擷取參數,是以可以處理get 方式中queryString的值,也可以處理post方式中 body data的值;

用來處理Content-Type: 為 application/x-www-form-urlencoded編碼的内容,送出方式GET、POST;

該注解有兩個屬性: value、required; value用來指定要傳入值的id名稱,required用來訓示參數是否必須綁定;

示例代碼:

@GetMapping("/tesRequestParam")

public Result tesRequestParam(@RequestParam("username") String username) {

return ResultUtil.successResult(username);

}

@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裡,這種情況在某些特殊需求下使用,詳情檢視FormHttpMessageConverter api;

示例代碼:

@PostMapping("/tesRequestBody")

public Result tesRequestBody(@RequestBody User user) {

return ResultUtil.successResult(user);

}

結果截圖:

springmvc怎麼解析post_SpringMVC 參數綁定注解解析

@RequestBody通過list接收對象數組

在我們傳遞對象的時候,無論Content-Type是x-www-form-urlencoded還是application/json其實沒有多大的關系,可是當我們需要傳遞對象數組的時候,表單編碼就不行了,這時我們是可以采用json傳遞,然後背景使用@RequestBody注解,通過list接收來對象數組。

前端代碼:

index.html

//打開頁面時運作

$(document).ready(function () {

var users = [];

var user1 = {"username": "dd", "password": "123"};

var user2 = {"username": "gg", "password": "123"};

users.push(user1);

users.push(user2);

$.ajax({

type: "POST",

url: "users/saveUsers",

timeout: 30000,

dataType: "json",

contentType: "application/json",

data: JSON.stringify(users),

success: function (data) {

//将傳回的資料展示成table

showTable(data);

},

error: function () { //請求出錯的處理

$("#result").text("請求出錯");

}

});

});

背景代碼:

@PostMapping("saveUsers")

public Result saveUsers(@RequestBody List users) {

return ResultUtil.successResult(users);

}

結果截圖:

springmvc怎麼解析post_SpringMVC 參數綁定注解解析

@SessionAttribute

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

示例代碼:

@PostMapping("/setSessionAttribute")

public Result setSessionAttribute(HttpSession session, String attribute) {

session.setAttribute("attribute", attribute);

return ResultUtil.SUCCESS_RESULT;

}

@GetMapping("/getSessionAttribute")

public Result getSessionAttribute(@SessionAttribute("attribute") String attribute) {

return ResultUtil.successResult(attribute);

}

我們首先給session添加一個attribute,然後再取出這個attribute。

springmvc怎麼解析post_SpringMVC 參數綁定注解解析
springmvc怎麼解析post_SpringMVC 參數綁定注解解析

@ModelAttribute

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

方法使用@ModelAttribute标注

标注在方法上的@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可以同時對許多控制器生效。

屬性名沒有被顯式指定的時候又當如何呢?在這種情況下,架構将根據屬性的類型給予一個預設名稱。舉個例子,若方法傳回一個Account類型的對象,則預設的屬性名為"account"。可以通過設定@ModelAttribute标注的值來改變預設值。當向Model中直接添加屬性時,請使用合适的重載方法addAttribute(..)-即帶或不帶屬性名的方法。

@ModelAttribute标注也可以被用在@RequestMapping方法上。這種情況下,@RequestMapping方法的傳回值将會被解釋為model的一個屬性,而非一個視圖名,此時視圖名将以視圖命名約定來方式來确定。

方法參數使用@ModelAttribute标注

标注在方法參數上的@ModelAttribute說明了該方法參數的值将由model中取得。如果model中找不到,那麼該參數會先被執行個體化,然後被添加到model中。在model中存在以後,請求中所有名稱比對的參數都會填充到該參數中。

這在Spring MVC中被稱為資料綁定,一個非常有用的特性,我們不用每次都手動從表格資料中轉換這些字段資料。

@PostMapping

public Result saveUser(@ModelAttribute User user) {

return ResultUtil.successResult(user);

}

以上面的代碼為例,這個User類型的執行個體可能來自哪裡呢?有幾種可能:

它可能因為@SessionAttributes标注的使用已經存在于model中

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

它可能是由URI模闆變量和類型轉換中取得的

它可能是調用了自身的預設構造器被執行個體化出來的

@ModelAttribute方法常用于從資料庫中取一個屬性值,該值可能通過@SessionAttributes标注在請求中間傳遞。在一些情況下,使用URI模闆變量和類型轉換的方式來取得一個屬性是更友善的方式。

在不給定注解的情況下,參數是怎樣綁定的?

通過分析AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter的源代碼發現,方法的參數在不給定參數的情況下:

若要綁定的對象時簡單類型:調用@RequestParam來處理的。

這裡的簡單類型指Java的原始類型(boolean, int 等)、原始類型對象(Boolean, Int等)、String、Date等ConversionService裡可以直接String轉換成目标對象的類型。也就是說沒有特别需求,不推薦使用@RequestParam。

若要綁定的對象時複雜類型:調用@ModelAttribute來處理的。也就是說如果不需要從model或者session中得到資料,@ModelAttribute可以不使用。

@RequestMapping支援的方法參數

下面這些參數Spring在調用請求方法的時候會自動給它們指派,是以當在請求方法中需要使用到這些對象的時候,可以直接在方法上給定一個方法參數的申明,然後在方法體裡面直接用就可以了。

HttpServlet 對象,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 對象。 但是有一點需要注意的是在使用HttpSession 對象的時候,如果此時HttpSession 對象還沒有建立起來的話就會有問題。

Spring 自己的WebRequest 對象。 使用該對象可以通路到存放在HttpServletRequest 和HttpSession 中的屬性值。

InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是針對HttpServletRequest 而言的,可以從裡面取資料;OutputStream 和Writer 是針對HttpServletResponse 而言的,可以往裡面寫資料。

使用@PathVariable 、@RequestParam 、@CookieValue 和 @RequestHeader 标記的參數。

使用@ModelAttribute 标記的參數。

java.util.Map 、Spring 封裝的Model 和ModelMap 。 這些都可以用來封裝模型資料,用來給視圖做展示。

實體類。 可以用來接收上傳的參數。

Spring 封裝的MultipartFile 。 用來接收上傳檔案的。

Spring 封裝的Errors 和BindingResult 對象。 這兩個對象參數必須緊接在需要驗證的實體對象參數之後,它裡面包含了實體對象的驗證結果。

一個參數傳多個值

在浏覽器輸入此URLhttp://localhost:8080/admin/login.action?username=geek&password=geek&password=geek

結果得到的對象為 : Manager{username='geek', password='geek,geek'}

參考文檔: