SpringMVC 引數繫結詳解
概述
記得之前跟前端同事聯調介面的時候,後端springMVC需要接收陣列型別的引數,然後跟前端說需要傳陣列型別過來。後來前端童鞋傳了陣列,但是後端接收不成功,聯調失敗。那時候由於時間關係沒有仔細研究這塊,當時想了個辦法就是前端傳一個json字串,後端換成接收json字串然後轉成需要的陣列物件。這顯然不是一種好的做法,框架幫我們做好的事我們沒有用上,還平白多了兩次資料的轉換。所以今天花時間研究了下,將springMVC的資料繫結做個總結。
1. 簡單型別引數
即幾種java原生的基本資料型別已經其封裝類以及String型別。比較簡單,選一種布林型別來講解。
測試程式碼:
@RequestMapping (value = "test")
@ResponseBody
public Object testDataBind(@RequestParam(name = "test") Boolean test) {
System.out.println(test);
return "success";
}
使用postman工具傳送請求:
控制檯輸出:
true
這種的比較簡單,沒有太多可說的。這裡需要注意的是,引數如果沒有加@RequestParam註解的話,傳參需要預設引數的名稱test作為傳參引數的名稱,而且沒有加註解的話,前端在傳送http請求的時候可以不傳該引數,也不會報錯。但是如果加了該註解,在沒有設定註解的屬性required = false的前提下,該引數必傳,不然會報400錯誤。如果該註解中指定了name屬性,name前端需要以name的值作為前端傳參名稱,如果沒有指定name屬性,在按引數名稱test為前端傳參名稱。
2. 簡單型別陣列/list
分別為兩種情況:
1) 直接使用陣列作為方法的引數,可以用@RequestParam註解修飾,如果使用List,必須使用@RequestParam註解修飾
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(String[] tests) {
System.out.println(tests[0] + " " + tests[1]);
return "success";
}
這種前端傳參需要遵守一定格式。
- form表單
表單元素name的值必須一樣
name="tests" value="arony1"
name="tests" value="arony2"
postman傳送請求:
控制檯輸出:
arony1 arony2
- ajax
陣列各個元素值需用“,”隔開。
data:{"tests":"arony1,arony2"}
值得注意的是,如果後端的springMVC方法引數用的是陣列來接收的話,前端用ajax傳送請求,那麼只能用上面這一種格式傳參,使用下面說的tests[0],tests[1]傳參是不行的。
postman傳送請求:
控制檯輸出:
arony1 arony2
2)使用自定義類裡面封裝一個數組或者List,用自定義類例項作為方法引數,不能用@RequestParam註解修飾
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(Person person) {
System.out.println(person.getTests()[0] + " " + person.getTests()[1]);
return "success";
}
Person:
public class Person {
private String[] tests;
public String[] getTests() {
return tests;
}
public void setTests(String[] tests) {
this.tests = tests;
}
}
- form表單
有兩種形式進行傳值
name="tests" value="arony1"
name="tests" value="arony2"
name="tests[0]" value="arony1"
name="tests[1]" value="arony2"
postman傳送請求:
控制檯輸出:
arony1 arony2
ajax
ajax也有兩種方式傳值:
data:{"tests":"arony1,arony2"}
data:{"tests[0]":"arony1","tests[1]":"arony2"}
效果跟表單完全一樣。
3. 自定義型別
首先定義一個自定型別User,包含以下屬性,生成get/set方法,toString方法:
private Integer id;
private String loginname;
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(User user) {
System.out.println(user);
return "success";
}
postman傳送請求:
控制檯輸出:
User{id=1, loginname='arony'}
可以看到,跟User屬性名一樣的引數如果傳了值,就可以被User物件所接受,沒有傳的為預設值。
我們嘗試下,給引數user加上@RequestParam註解看看。使用postman傳送請求,會發現返回400。所以我們要理解@RequestParam註解含義,它標示的是該方法引數接受的是一個http引數。因此,如果是用一個自定義物件作為引數的話,不要在之前加上@RequestParam,因為SpringMVC在解析http請求的引數user的時候,不能將接收到的引數轉化成一個User物件。
4. 自定義型別陣列/list
注意:這種情況只能使用一個自定義類來包裝陣列/list。
再定義一個引數類:
public class Parameter {
private Person[] person;
public Person[] getPerson() {
return person;
}
public void setPerson(Person[] person) {
this.person = person;
}
}
Person:
public class Person {
private String tests;
public String getTests() {
return tests;
}
public void setTests(String tests) {
this.tests = tests;
}
}
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(Parameter parameter) {
System.out.println(parameter.getPerson()[0].getTests() + " " + parameter.getPerson()[1].getTests());
return "success";
}
- form表單傳參
name="person[0].tests" value="arony1"
name="person[1].tests" value="arony2"
- ajax傳參
data:{"person[0].tests":"arony1","person[1].tests":"arony2"}
postman傳送請求:
控制檯輸出:
arony1 arony2
5. Map<
String,基本型別>
與上面一樣 這種情況只能使用一個自定義類來包裝map。
Parameter:
public class Parameter {
private Map<String, String> map;
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(Parameter parameter) {
parameter.getMap().forEach((key, value) -> {
System.out.println(key + " " + value);
});
return "success";
}
前端傳參格式:
- form表單
name="map[key1]" value="arony1"
name="map[key2]" value="arony2"
或者
name="map.key1" value="arony1"
name="map.key2" value="arony2"
- ajax
data:{"map[key1]":"arony1","map[key2]":"arony2"}
或者
data:{"map.key1":"arony1","map.key2":"arony2"}
postman傳送請求:
控制檯輸出:
key1 arony1
key2 arony2
6. Map<
String, 自定義類>
跟5是很類似的。
Parameter:
public class Parameter {
private Map<String, Person> map;
public Map<String, Person> getMap() {
return map;
}
public void setMap(Map<String, Person> map) {
this.map = map;
}
}
Person:
public class Person {
private String tests;
public String getTests() {
return tests;
}
public void setTests(String tests) {
this.tests = tests;
}
}
介面程式碼:
@RequestMapping(value = "test")
@ResponseBody
public Object testDataBind(Parameter parameter) {
parameter.getMap().forEach((key, value) -> {
System.out.println(key + " " + value.getTests());
});
return "success";
}
前端傳參格式:
- form表單
name="map[key1].tests" value="arony1"
name="map[key2].test2" value="arony2"
這裡注意,name=”map.key1.tests” value=”arony1”這樣傳值是不行的。必須用方括號。
- ajax
data={"map[key1].tests":"arony1","map[key2].test2":"arony2"}
這裡也必須使用方括號。
使用postman傳送請求:
控制檯輸出:
key1 arony1
key2 arony2
總結
以上的SpringMVC引數繫結可以總結為下圖:
其中,Map<
String, ①>
前端還可以使用“.”代替方括號。