Spring MVC數據綁定方式

 定義:簡單綁定是將一個用戶界面元素(控件)的屬性綁定到一個類型(對象)實例上的某個屬性的方法。

基本類型、包裝類型、數組(以參數age為例)

一、基本類型

1、key是必須的,即age是必須傳值的

2、隻能是int類型,即傳給age的值必須為int類型且范圍也隻能是int類型

如果沒有傳age,後臺會報500錯誤,會提示當前的age是不可以為空的

如果age傳一個字符串abc,Spring MVC會進行攔截,報400參數錯誤異常

@Controller
public class TestController{
    /*
        RequestMapping註解
        value:RequestMapping的屬性,指定請求的實際地址
        method:RequestMapping的屬性,指定請求的method類型,分為GET、POST、PUT、DELETE等
        headers:RequestMapping的屬性
                 指定request中必須包含指定的header值,才能處理該請求
    */
    @RequestMapping(value = "baseType.do", method = RequestMethod.GET)
    @ResponseBody    //方法的返回值會放到ResponseBody數據區裡
    /*
        RequestParam註解
        value:RequestParam的屬性,起別名
        required:RequestParam的屬性,是否必傳,默認值是true
    */
    public String baseType(@RequestParam(value = "xage") int age){
        return "age:" + age;
    }
}

二、包裝類型

1、可以不傳key,即age可以為空

@Controller
public class TestController{
    @RequestMapping(value = "baseType.do")
    @ResponseBody
    public String baseType(Integer age){
        return "age:" + age;
    }
}

此時訪問localhost:8080/baseType.do,前臺顯示age:null

註意:在開發過程中,對可能為空的數據,最好將參數數據定義為包裝類型

三、數組

一次性傳多個值,例如基本類型、包裝類型、String的對象類型

@Controller
public class TestController{
    @RequestMapping(value = "array.do")
    @ResponseBody
    public String array(String[] age){
        StringBuilder sdf = new StringBuilder();
        for(String item : age){
            sbf.append(item).append(" ");
        }
        return sbf.toString();
    }
}

此時訪問localhost:8080/array.do?age=17&age=18,前臺顯示17 18

簡單對象、多層級對象、同屬性對象

一、簡單對象(User類:name, age)

@Controller
public class TestController{
    @RequestMapping(value = "object.do")
    @ResponseBody
    public String object(User user){
        return user.toString();
    }
}

此時訪問localhost:8080/object.do?name=Tom&age=18,前臺顯示User{name='Tom',age=18}

二、多層級對象(User類:name, age, contactInfo、ContactInfo類:phone, adress)

@Controller
public class TestController{
    @RequestMapping(value = "object.do")
    @ResponseBody
    public String object(User user){
        return user.toString();
    }
}

此時訪問localhost:8080/object.do?name=Tom&age=18&contactInfo.phone=10000

前臺顯示User{name='Tom',age=18,contactInfo={phone='10000',address='null'}}

三、同屬性對象(User類:name, age、Admin類:name, age)

@Controller
public class TestController{
    @RequestMapping(value = "object.do")
    @ResponseBody
    public String object(User user, Admin admin){
        return user.toString() + " " + admin.toString();
    }
}

此時訪問localhost:8080/object.do?name=Tom&age=18,前臺顯示User{name='Tom',age=18} Admin{name='Tom',age=18}

@Controller
public class TestController{
    @RequestMapping(value = "object.do")
    @ResponseBody
    public String object(User user, Admin admin){
        return user.toString() + " " + admin.toString();
    }
}
 
@InitBinder("user")    //綁定前綴
public void initUser(WebDataBinder binder){
    binder.setFieldDefaultPrefix("user.");
}
 
@InitBinder("admin")    //綁定前綴
public void initUser(WebDataBinder binder){
    binder.setFieldDefaultPrefix("admin.");
}

此時訪問localhost:8080/object.do?user.name=Tom&admin.name=Lucy&age=18

前臺顯示User{name='Tom',age=18} Admin{name='Lucy',age=18}

如果沒有@InitBinder註解的輔助方法,這個方法如果傳遞user.name,admin.name結果會怎麼樣呢?

如果沒有@InitBinder註解的輔助方法,Spring MVC會認為是User類和Admin類裡面的user字段的name,所以前臺顯示null

List、Set、Map

一、List

@Controller
public class TestController{
    @RequestMapping(value = "list.do")
    @ResponseBody
    public String list(UserList userList){
        return userList.toString();
    }
}

Spring MVC關於集合綁定需要一個data收集的對象,單純的綁定是無效的。 

建一個UserList類:

public class UserList{
    private List<User> users;
    
    public List<User> getUsers(){
        return users;
    }
 
    public void setUsers(List<User> users){
        this.users = users;
    }
 
    @Override
    public String toString(){
        return "UserList{" +
                "users=" + users +
                '}';
    }
}

此時訪問localhost:8080/list.do?users[0].name=Tom&users[1].name=Lucy

前臺顯示UserList{users=[User{name='Tom', age=null, contactInfo=null}, User{name='Lucy', age=null, contactInfo=null}]}

註意:如果訪問傳值的時候,users[0]直接跨到users[10],即訪問

localhost:8080/list.do?users[0].name=Tom&users[10].name=Lucy

則前臺顯示users[1]到users[9]以及users[11]為空對象,所以請求索引的時候一定要是連續的,否則會浪費資源

二、Set

Set相對List來說有一定的局限性,它需要先初始化Set,而List是不需要的

Set在實際應用場景當中,大部分是做對象的重復判斷或排除重復

例如一個Student對象(姓名和Email),如果姓名和Email相同,則認為這個對象是重復的,此時需要重寫hashcode方法和equals方法,然後在方法裡寫重復判斷的邏輯(綁定到一個對象上)

@Controller
public class TestController{
    @RequestMapping(value = "set.do")
    @ResponseBody
    public String set(UserSet userSet){
        return userSet.toString();
    }
}

Set和List一樣,也需要一個data收集的對象

public class UserSet{
    private Set<User> users;
    
    //Set和List有一些區別,就是對它本身的初始化有一些要求
    private UserSet(){
        users = new LinkedHashSet<User>();
        users.add(new User());
        users.add(new User());
    }
 
    public Set<User> getUsers(){
        return users;
    }
 
    public void setUsers(Set<User> users){
        this.users = users;
    }
 
    @Override
    public String toString(){
        return "UserSet{" +
                "users=" + users +
                '}';
    }
}

此時訪問localhost:8080/set.do?users[0].name=Tom&users[1].name=Lucy

前臺顯示UserSet{users=[User{name='Tom', age=null, contactInfo=null}, User{name='Lucy', age=null, contactInfo=null}]}

如果跨界訪問,即訪問localhost:8080/set.do?users[0].name=Tom&users[10].name=Lucy

則會報錯,因為已經定義瞭Set的size為2

註意:如果沒有重寫hashcode方法和equals方法進行排重,則傳兩個相同對象的時候前臺還會顯示兩個對象

可是如果定義瞭Set的size為2,而又重寫瞭hashcode方法和equals方法進行排重,那麼當我們傳兩個相同對象的時候則會拋異常,因為初始化Set的時候定義的是兩個空對象,可是經過hashcode方法和equals方法判

斷完之後會認為是重復的對象,所以初始化的Set的size則為1,此時傳兩個對象就會報錯,所以Spring MVC對Set的支持並不友好

三、Map

@Controller
public class TestController{
    @RequestMapping(value = "map.do")
    @ResponseBody
    public String map(UserMap userMap){
        return userMap.toString();
    }
}

Map和List一樣,也需要一個data收集的對象

public class UserMap{
    private Map<String,User> users;
    
    public Map<User> getUsers(){
        return users;
    }
 
    public void setUsers(Map<String,User> users){
        this.users = users;
    }
 
    @Override
    public String toString(){
        return "UserMap{" +
                "users=" + users +
                '}';
    }
}

此時訪問localhost:8080/map.do?users["X"].name=Tom&users["X"].age=10&users["Y"].name=Lucy

前臺顯示UserMap{users={X=User[name='Tom', age=10, contactInfo=null}, Y=User{name='Lucy', age=null, contactInfo=null}}}

JSON、XML

RequestBody註解用於讀取Request請求的Body部分數據,使用系統默認配置的HttpMessageConverter進行解析,然後把相應的數據綁定到要返回的對象上;再把HttpMessageConverter返回的對象數據綁定到Controller中方法的參數上。

RequestBody註解常用來處理Content-Type不是默認的application/x-www-form-urlcoded編碼的內容,比如說:application/json或者是application/xml等。一般情況下來說常用其來處理application/json類型。

一、JSON

@Controller
public class TestController{
    @RequestMapping(value = "json.do")
    @ResponseBody
    public String json(@RequestBody User user){
        return user.toString();
    }
}

利用PostMan等工具傳值:

{
    "name":"Jim",
    "age":16,
    "contactInfo":{
    "address":"beijing",
    "phone":"10010"
    }
}

返回值:

User{name='Jim', age=16,
contactInfo=ContactInfo{phone='10010',
address='beijing'}}

二、XML

這個功能需要spring-oxm依賴包提供支持以及在實體類中添加一些註解

@XmlRootElement(name="admin")
public class Admin{
    private String name;
    
    private String age;
    
    @XmlElement(name="name")
    public String getName() { return name; }
    
    public void setName(String name) { this.name = name; }
 
    @XmlElement(name="age")
    public Integer getAge() { return age; }
    
    public void setAge(String age) { this.age = age; }
 
    @Override
    public String toString(){
        return "Admin{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

@Controller
public class TestController{
    @RequestMapping(value = "xml.do")
    @ResponseBody
    public String xml(@RequestBody User user){
        return user.toString();
    }
}

利用PostMan等工具傳值:

<?xml version="1.0" encoding="UTF-8" ?>
<admin>
    <name>Jim</name>
    <age>16</age>
</admin>

返回值:

Admin{name='Jim', age=16}

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: