前面已經寫過 SSM 三大框架的一些入門文章,在 SpringMVC 部分,關於參數的綁定提的不是太多,從新整理了一下,就當作一個補充,時間匆匆,可能會有一些錯誤,你們能夠共同交流,一塊兒探討!javascript
注:下面的文章,重點仍是參數綁定的使用,關於導包或者一些註解的講解,我沒有多說,以前的文章一些經常使用的也都還介紹過,若是有必要,我再整理一篇關於註解的總結也能夠哈 ~php
【萬字長文】Spring MVC 層層遞進輕鬆入門 !html
咱們假定要請求的參數爲 age ,那麼咱們有兩種選擇 :即 ① 傳入基本類型 int ② 傳入包裝類型 Integer ,咱們這一塊的講解,就用它們兩個來說解java
注:咱們將重心放在參數綁定上,項目名或者Controller上的@RequestMapping註解,我都沒加ajax
@RequestMapping("baseType.do")
@ResponseBody
public String baseType(int age) {
return "age:" + age;
}
複製代碼
http://localhost:8080/baseType.do?age=30
spring
當咱們請求時,返回結果:age:30json
這裏有一個問題須要提一下,你們應該知道一個註解 @RequestParam ,咱們是否可經過這個註解的 required 屬性,幫助咱們規避這個請求參數爲空的問題呢?後端
答案是否認的,雖然這個註解設置 required = false 後不傳值後臺也不會報錯,可是若是其中指定了基本數據類型,例如咱們代碼中的 int 這個時候若是不傳值是依舊會報一個 500 錯誤數組
由於其不傳值就賦 null,可是 int 類型卻不能爲null
因此想要規避這個參數爲空的問題,咱們就能夠選擇包裝類型 Integer
@RequestMapping("packingType.do")
@ResponseBody
public String packingType(Integer age) {
return "age:" + age;
}
複製代碼
http://localhost:8080/packingType.do?age=30
正常返回:age:30
http://localhost:8080/packingType.do
http://localhost:8080/packingType.do?
http://localhost:8080/packingType.do?=
參數爲空不報錯,均返回:age:null
什麼是多層級對象,先別急,先看一個最基礎的例子
咱們首先建立一個用戶類
public class User {
private String id;
private String name;
......補充其 get set toString 方法
}
複製代碼
直接在參數中寫上對應 User 類型就能夠了
@RequestMapping("objectType.do")
@ResponseBody
public String objectType(User user) {
return user.toString();
}
複製代碼
http://localhost:8080/objectType.do?id=001&name=Steven
返回結果:User{uid='001', name='Steven'}
若是這個時候,我建立一個新的類 UserDetails
public class UserDetails {
private Integer age;
private String address;
......補充其 get set toString 方法
}
複製代碼
在 User 類中引入這個類,這種狀況又該如何綁定參數呢
public class User {
private String id;
private String name;
private UserDetails userDetails;
......補充其 get set toString 方法
}
複製代碼
http://localhost:8080/objectType.do?id=1&name=Steven&userDetails.age=20&userDetails.address=BeiJing
返回結果:User{uid='1', name='Steven', userDetails=UserDetails{age=20, address='BeiJing'}}
userDetails.address=xxxxx
若是咱們想要直接接收兩個對象,有時候免不了有相同的成員,例如咱們的 User 和 Student 類中均含有
Integer id 、String name 兩個成員,咱們試着請求一下
@RequestMapping("objectType2.do")
@ResponseBody
public String objectType2(User user, Student student) {
return user.toString() + " " + student.toString();
}
複製代碼
http://localhost:8080/objectType2.do?id=8&name=Steven
返回結果:User{id='8', name='Steven'} Student{id='8', name='Steven'}
能夠看到,兩個對象的值都被賦上了,可是,大部分狀況下,不一樣的對象的值通常都是不一樣的,爲此,咱們還有解決辦法
@InitBinder 註解能夠幫助咱們分開綁定,下面的代碼也就是說分別給 user、student 指定一個前綴
@InitBinder("user")
public void initUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
@InitBinder("student")
public void initStudent(WebDataBinder binder) {
binder.setFieldDefaultPrefix("stu.");
}
複製代碼
http://localhost:8080/objectType2.do?user.id=1&name=Steven&stu.id=002
當發起這樣一個請求後,咱們分別指定了 user 和 student 的 id 值,而 name 則是一樣的 Steven
返回結果:User{id='1', name='Steven', userDetails=null} Student{id='2', name='Steven'}
@RequestMapping("arrayType.do")
@ResponseBody
public String arrayType(String[] nickname) {
StringBuilder sb = new StringBuilder();
for (String s : nickname) {
sb.append(s).append(", ");
}
return sb.toString();
}
複製代碼
http://localhost:8080/arrayType.do?nickname=Jack&nickname=Steven&nickname=Tom
返回結果:Jack, Steven, Tom,
集合是不能直接進行參數綁定的,因此咱們須要建立出一個類,而後在類中進行對 List 的參數綁定
首先建立 UserList 類,其中我爲了演示,只放了 private List<User> users
補充好 get set toString 方法
控制層方法中,參數就是這個建立出來的類
@RequestMapping("listType.do")
@ResponseBody
public String listType(UserList userList) {
return userList.toString();
}
複製代碼
http://localhost:8080/listType.do?users[0].id=1&users[0].name=Jack&users[1].id=2&users[1].name=Marry
咱們的請求,分別將兩個user信息存入了 List<User> users
中
特別注意:若是你的 Tomcat 版本是 7.0 左右 那麼上述請求是沒問題的,可是若是版本比較高,例如我自己所用的 Tomcat 8.5 ,若是執行上述請求就會報 400 錯誤
HTTP Status 400 – Bad Request
Message Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
這是由於Tomcat高的版本地址中不能使用「[」和「]」 ,咱們能夠將其換成對應的16進制,即 「[」 換成 %5B,「]」 換成 %5D
http://localhost:8080/listType.do?users%5B0%5D.id=1&users%5B0%5D.name=Jack&users%5B1%5D.id=2&users%5B1%5D.name=Marry
或者直接用 post 請求也是能夠的哈
map 類型是同樣的套路,咱們先建立一個 UserMap類,而後在其中聲明 private Map<String,User> users
進而綁定參數
@RequestMapping("mapType.do")
@ResponseBody
public String mapType(UserMap userMap) {
return userMap.toString();
}
複製代碼
http://localhost:8080/mapType.do?users['userA'].id=1&users['userA'].name=Jack&users['userB'].id=2&users['userB'].name=Tom
一樣 「[]」 會遇到上面的錯誤,因此若是想要在地址欄請求訪問,就須要替換字符,或者發起一個 post 請求
http://localhost:8080/mapType.do?users%5B%27userA%27%5D.id=1&users%5B%27userA%27%5D.name=Jack&users%5B%27userB%27%5D.id=2&users%5B%27userB%27%5D.name=Tom
返回結果:UserMap{users={userA=User{id='1', name='Jack'}, userB=User{id='2', name='Tom'}}}
除了前面表單等提交的方式,咱們還有一種ajax的提交方式,經常用來向後端傳遞以及接受 json 格式的數據,關於 json 字符串和對象之間的轉換會用到下面的 jar包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.0</version>
</dependency>
複製代碼
這一塊的演示,咱們建立一個 Admin 實體類
public class Admin {
private Integer id;
private String name;
......補充其 get set toString 方法
}
複製代碼
當 ajax 傳遞的參數不少的時候,使用參數名匹配,會很是麻煩,若是請求的參數在後臺中有一個匹配的實體類,咱們就能夠選擇前臺傳一個 json 到後臺,後臺使用匹配的實體類進行接收
提交 JSON: {"id": "37","name": "張三"}
$(function () {
$("#btn").click(function () {
//發送ajax請求
$.ajax({
url:"ajaxType1.do",
contentType:"application/json",
data:'{"id":"37","name":"張三"}',
dataType:"json",
type:"post",
success:function (data) {
//解析響應數據
alert(data.id);
alert(data.name);
}
})
});
});
複製代碼
Contoller
//用實體接參數
@RequestMapping("ajaxType1.do")
@ResponseBody
public Admin ajaxType1(@RequestBody Admin admin) {
System.out.println(admin.toString());
admin.setName("測試管理員");
return admin;
}
複製代碼
後端參數中的 admin 就會被綁定好參數,供開發者使用
@RequestBody
註解經常使用來處理 content-type
不是默認的application/x-www-form-urlcoded
編碼的內容,說常處理application/json
類型
還有一種狀況,那就是請求的參數仍然挺多,可是後臺也沒有一個合適的實體進行匹配,咱們也能夠考慮使用map來接收
依舊提交 JSON: {"id": "37","name": "張三"}
$(function () {
$("#btn").click(function () {
//發送ajax請求
$.ajax({
url:"ajaxType1.do",
contentType:"application/json",
data:'{"id":"37","name":"張三"}',
dataType:"json",
type:"post",
success:function (data) {
//解析響應數據
alert(data.id);
alert(data.name);
}
})
});
});
複製代碼
可是 Controller 中咱們使用 map 來進行接收,而後簡單給了一個實例,將map值封裝到 Admin 對象中,而後返回到前端去
@RequestMapping("ajaxType3.do")
@ResponseBody
public Admin ajaxType3(@RequestBody Map<String, String> map) {
Integer id = null;
String name = null;
if (map.containsKey("id")){
id = Integer.parseInt(map.get("id"));
}
if (map.containsKey("name")){
name = map.get("name");
}
Admin admin = new Admin();
admin.setId(id);
admin.setName(name);
return admin;
}
複製代碼
一樣的,咱們還可使用 list 方式進行接收,它時以 json 數組的形式傳遞的
var listType=[];
var admin={};
admin.id=1;
admin.name='湯姆';
listType.push(admin);
var admin2={};
admin2.id=2;
admin2.name='傑克';
listType.push(admin2);
$(function () {
$("#btn").click(function () {
//發送ajax請求
$.ajax({
url:"ajaxType1.do",
contentType:"application/json",
data:JSON.stringify(listType),
dataType:"json",
type:"post",
success:function (data) {
//解析響應數據
alert(data.id);
alert(data.name);
}
})
});
});
複製代碼
去後臺看一下
@RequestMapping("ajaxType5.do")
@ResponseBody
public void ajaxType5(@RequestBody List<Admin> list) {
System.out.println(list);
for (Admin admin : list){
System.out.println(admin.getId() + " " + admin.getName());
}
}
複製代碼
看一下控制檯的輸出:
[Admin{id='1', name='湯姆'}, Admin{id='2', name='傑克'}]
1 湯姆
2 傑克
複製代碼
這是用來提交的表單
<form id="ajaxForm" method="post">
id:<input type="text" name="id">
name:<input type="text" name="name">
</form>
複製代碼
這是 ajax請求,咱們也經常使用$("#ajaxForm").serialize()
進行一個表單的序列化,而後提交,可是它只是將Form序列化拼接成了簡單的字符串,並非JSON格式,它是例如這樣的:
id=111&name=Steven
複製代碼
因此剛纔所說的json那一套就無論用了
$(function () {
$("#btn").click(function () {
//發送ajax請求
$.ajax({
url:"ajaxType1.do",
contentType:"application/json",
data:$("#ajaxForm").serialize(),
dataType:"json",
type:"post",
success:function (data) {
//解析響應數據
alert(data.id);
alert(data.name);
}
})
});
});
複製代碼
若是想要使用序列化,同時還想要傳遞 json 格式到後臺,也不是沒辦法
咱們須要添加一個方法
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
複製代碼
同時將下面 ajax 中的 data修改成
data:JSON.stringify($("#ajaxForm").serializeObject()),
複製代碼
後臺就能獲取到 json 格式了
{"id":"111","name":"Steven"}
複製代碼
後臺很是簡單,和前面沒什麼區別,咱們須要在實體中進行一些操做
@RequestMapping("xmlType.do")
@ResponseBody
public String xmlType(@RequestBody Student student) {
return student.toString();
}
複製代碼
這種狀況下,咱們須要藉助一個jar包 —— spring-oxm,本身能夠導入一下
而後咱們須要在接受的實體那裏,添加 @XmlRootElement 和 @XmlElement 註解,來表明根節點和子節點
package cn.ideal.Object;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "student")
public class Student {
private Integer id;
private String name;
@XmlElement(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
複製代碼
例如咱們xml爲
<?xml version="1.0" encoding="UTF-8" ?>
<student>
<id>66</id>
<name>Steven</name>
</student>
複製代碼
而後發起請求,注意將Content-Type 改成 application/xml
返回的結果:Student{id='66', name='Steven'}
若是文章中有什麼不足,歡迎你們留言交流,感謝朋友們的支持!
若是能幫到你的話,那就來關注我吧!若是您更喜歡微信文章的閱讀方式,能夠關注個人公衆號
在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤
一個堅持推送原創開發技術文章的公衆號:理想二旬不止