SpringMVC數據綁定接收復雜數據處理方案
常用於數據綁定的幾個注解@PathVariable,@RequestBody、@RequestParam,本文配合postman,講解常見的前后台數據交互中的一些數據綁定的問題
@PathVariable
PathVariable是路徑變量的意思,這個注解主要作用在請求URL路徑上的數據綁定,默認傳遞數值寫在URL上,SpringMVC就可以獲取到
- 支持請求方式:GET
- 參數傳遞:在URL上直接傳遞
@RequestMapping("/Student")
@RestController
public class DataBindController {
@Autowired
private StudentService studentService;
@GetMapping("/getStudent/{id}")
public Student getStudentById(@PathVariable Integer id){
Student student = studentService.getStudentById(id);
return student;
}
}

@RequestBody
RequestBody是請求體的意思,這個注解作用在請求體的數據綁定,並且數據必須在寫在請求體中,還要以JSON的數據格式發送才符合條件
該注解常用來處理Content-Type: 不是application/x-www-form-urlencoded編碼的內容,例如application/json, application/xml等;
- 支持請求方式:GET,POST,PUT,DELETE
- 參數傳遞:在Body中傳遞
- 支持的Content-Type:json
@PostMapping("/addStudent")
public Student addStudent(@RequestBody Student student){
System.out.println(student);
return student;
}

@RequestParam
RequestParam是請求參數的意思,這個注解的作用在請求路徑和請求體中的數據,因為使用request.getParameter()方式獲取參數
所以可以處理get 方式中queryString的值,也可以處理post方式中 body data的值
- 支持請求方式:GET,POST,PUT,DELETE
- 參數傳遞:在Body中傳遞
- 支持的Content-Type:json

在請求體中的參數必須指定是form-data或者x-www-form-urlencoded,這兩種方式是以表單的形式提交數據,使用這兩種方式
會將表單內的數據轉換為鍵值對,&分隔形式封裝在請求體中傳送給后台,前者和后者的區別是在於對非ASCII碼字符的轉碼,
前者是直接發送,后者是轉碼成百分號發送

三個注解小結
| 注解 | 請求參數位置 | 請求方式 | 支持的Content-Type | 請求示例 |
|---|---|---|---|---|
| @PathVariable | Url | Get | Get請求沒有Content-Type | /students/1 |
| @RequestParam | Url和Body | Get/Post/Put/Delete/Patch | form-data,x-www-form-urlencoded | /students?name=zs&age=23 |
| @RequestBody | Body | Post/Put/Delete/Patch | application/json | {"id":1,"name":"zs","age":23} |
三個注解的源碼和使用場景:
@PathVariable
這個注解我一般在工作中,會用在單個對象的查詢上,比如要根據ID值查詢學生信息,就會在Postman發送GET請求,后台使用@PathVariable接收
- 優點:適合接收簡單類型的數據綁定,如int,string這兩個常用
- 缺點:id暴露在url上,對於不方便泄露ID的值請求,最好不要使用。只支持Get方式,請求方式有局限性,不支持復雜數據類型,自定義數據類型
源碼
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
/**
* 參數名稱
*/
String value() default "";
}
源碼解析
-
@PathVariable注解源碼中只有一個參數,不填的默認是綁定到與路徑參數同名的形參變量
-
如果要接收多個路徑變量,則需要聲明多個@PathVariable變量
@RequestMapping("/Student/{name}/{age}")
public Object getStudentInfo (@PathVariable String name,@PathVariable Integer age){
//...
}
使用解析
- POSTMAN發送的鏈接:http://localhost:8080/Student/getStudent/1
- 后端接收參數:/Student/getStudent/{id},這里的id是路徑上的參數,傳什么值接收什么值
- 后端映射值:@PathVariable Integer id 這里的方法參數id要與路徑變量參數id同名,因為@PathVariable沒有指定別名的注解變量
@RequestParam
這個注解我一般在工作中,會用在組合查詢多個對象,比如跟據姓名模糊查詢和性別組合查詢篩選學生,就會發送POST請求,后台使用RequestParam接收
- 優點:支持常用多種請求方式,請求參數可以封裝在請求體中較為安全
- 缺點:id暴露在url上,對於不方便泄露ID的值請求,最好不要使用。只支持Get方式,請求方式有局限性
源碼
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
/**
* 參數名稱(和value同等意思)
*/
@AliasFor("name")
String value() default "";
/**
* 參數名稱 (和name同等意思)
*/
@AliasFor("value")
String name() default "";
/**
* 是否必選(默認必選)
*/
boolean required() default true;
/**
* 參數默認值
*/
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
源碼解析
@RequestParam總體上來說,該注解類擁有三個參數:
-
value、name 屬性都標識請求參數名(必須配置)
-
required:參數是否必傳,默認為 true,可以設置為非必傳 false;(如果設置了必傳或默認,請求未傳遞參數,將會拋出異常)
-
defaultValue:參數默認值,如果設置了該值,required 將會自動設置為 false
使用解析
-
get請求的 requestHeaders 中 content-type 這個字段,使用 form-data 表單形式攜帶參數請求
-
Spring中的@RequestParam注解接收的參數大多數場景是來自Request Headers中,
-
即請求頭,也就是url中,格式為:
http://localhost:8080?name=zs&age=23,由於 url 長度有限制,所以參數需要限制數量和值得長度
@RequestBody
源碼
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
/**
* 默認參數必傳
*/
boolean required() default true;
}
源碼解析
- @RequestBody注解只擁有一個參數
- required 默認為 true,即對象中的屬性必須有一個要傳,否則會拋出異常
使用解析
-
post請求的requestHeaders請求頭中有content-type字段,一般用來處理:applicatin/json格式的參數;
-
Spring中的@RequestBody注解是用來接收請求體中的參數數據,即requestBody請求體中,故不受參數數據長度的限制;
補充HTTP知識:Post、Get、Put、Delete
Http協議常用的四種請求方式:Post、Get、Put、Delete等;其中Put、Delete請求方式很少見,都可用Post方式代替!
- 對數據庫而言: get 請求不修改數據庫,只是查詢。Post是增加記錄,put是更新,Delete數據庫刪除;
- Put,Post,Delete 方式的請求參數會直接放在requestBody里;
- 處理 request uri 部分的注解,路徑參數變量:@PathVariable;
- 處理request header部分的注解: @RequestHeader, @CookieValue,@RequestParam;
- 處理request body部分的注解:@RequestParam, @RequestBody;
- 綜上所述:@RequestParam注解既可以接收Get方式的請求頭中的參數,也可以接收Post方式的請求體中的參數;
補充HTTP知識: Content-Type與Accept
--------Response Headers-----------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
If-Modified-Since: 0
expire: 0
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 17 Nov 2020 05:48:54 GMT
--------Request Headers-----------
POST /student/update HTTP/1.1
Host: localhost:9002
Connection: keep-alive
Content-Length: 21
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json
X-Requested-With: XMLHttpRequest
User-Agent: Chrome/86.0.4240.75 Mobile Safari/537.36
Content-Type: application/json
Accept
Accept代表發送希望接受的數據類型
比如:Accept:application/json;
比如我們用瀏覽器發送請求中,請求頭Request Headers帶有Accept:application/json; ,
那就是表明瀏覽器發送這個請求,希望服務器傳送回的數據格式是json數據格式
Content-Type
Content-Type代表發送端發送的數據類型
比如:Content-Type:application/json;
Response Headers帶有Content-Type: application/json就代表服務器希發送數據類型是json類型
Request Headers帶有Content-Type: application/json就代表服務器希發送數據類型是json類型
上述報文解釋
瀏覽器發送了POST請求,這次請求發送的數據格式是JSON數據給是,希望服務器能返回JSON的數據格式
服務器發送返回了JSON形式的數據格式數據給瀏覽器
常見Content-Type媒體類型
Get請求的 headers 中沒有 content-type 這個字段,Put、Delete和Post 請求的headers 是有 content-type 這個字段的
常見Content-Type媒體類型如下:
-
application/x-www-form-urlencoded 這種就是一般的文本表單用 post 傳地數據,
只要將得到的 data 用 @RequestParam 或 request.getParamter() 獲取即可;
-
multipart/form-data ,用於文件上傳,此時 form 的 enctype 屬性必須指定為 multipart/form-data;
-
application/json,將數據以json對象的格式傳遞;
-
text/xml;
