zoukankan      html  css  js  c++  java
  • Java Web 学习(5) —— Spring MVC 之数据绑定

    Spring MVC 之数据绑定

    数据绑定是将用户输入绑定到领域模型的一种特性。
    Http 请求传递的数据为 String 类型,通过数据绑定,可以将数据填充为不同类型的对象属性。

    基本类型绑定

    @RequestMapping("/int")
    @ResponseBody
    public String bindInt (int i) {
        return "bindInt:" + i;
    }
    

    请求:/int?i=10
    响应:bindInt:3

    错误请求:/int or /int?2
    错误代码:500

    基本类型数据绑定时,必须传入keyvalue

    包装类型绑定

    @RequestMapping("/integer")
    @ResponseBody
    public String bindInteger (Integer i) {
        return "bindInteger:" + i;
    }
    

    请求:/integer?i=5
    响应:bindInteger:5

    请求:/integer or /integer?5 or /integer?i or /integer?i=
    响应:bindInteger:null

    包装类型数据绑定时,keyvalue均可为空。
    若要求必须传入参数,可加@RequestParam

    @RequestMapping("/integer")
    @ResponseBody
    public String bindInteger (@RequestParam Integer i) {
        return "bindInteger:" + i;
    }
    

    错误请求:/integer or /integer?5
    错误代码:400

    请求:/integer?i or /integer?i=
    响应:bindInteger:null

    数组绑定

    @RequestMapping("/array")
    @ResponseBody
    public String bindArray (String[] strs) {
        StringBuilder sb = new StringBuilder();
        sb.append("bindArray:");
        for (String str : strs)
            sb.append(str + " ");
        return sb.toString();
    }
    

    请求:/array?strs=str1&strs=str2
    响应:bindArray:str1 str2

    简单对象绑定

    @RequestMapping("/user")
    @ResponseBody
    public String bindUser (User user) {
        return "bindUser:" + user.toString();
    }
    
    public class User {
        private String name;
        private Integer age;
        // getters and setters
        // toString
    }
    

    请求:/user?name=Tom&age=15
    响应:bindUser:User [name=Tom, age=15]

    多层级对象绑定

    public class User {
        private String name;
        private Integer age;
        private ContactInfo info;
        // getters and setters
        // toString
    }
    public class ContactInfo {
        private String phone;
        private String address;
        // getters and setters
        // toString
    }
    

    请求:/user?name=Tom&info.phone=123456
    响应:bindUser:User [name=Tom, age=null, info=ContactInfo [phone=123456, address=null]]

    同属性多对象绑定

    @RequestMapping("/userandadmin")
    @ResponseBody
    public String bindUserAndAdmin (User user, Admin admin) {
        return "bindUserAndAdmin:
    " + user.toString() + "
    " + admin.toString();
    }
    
    public class Admin {
        private String name;
        private Integer age;
        // getters and setters
        // toString
    }
    

    请求:/userandadmin?name=Tom&age=15
    响应:
    bindUserAndAdmin:
    User [name=Tom, age=15]
    Admin [name=Tom, age=15]

    数据同时被绑定到了具有相同属性的两个对象上。
    解决方式:

    @InitBinder("user") 
    public void initUser(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("user.");
    }
    
    @InitBinder("admin") 
    public void initAdmin(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("admin.");
    }
    

    请求:/userandadmin?user.name=Tom&age=15&admin.name=Jack
    响应:
    bindUserAndAdmin:
    User [name=Tom, age=15]
    Admin [name=Jack, age=15]

    InitBinder作用在该控制器中,进入控制器后先调用InitBinder后调用RequestMapping方法。
    不配置InitBinder加前缀无效,不能成功绑定。

    WebDataBinder用来绑定请求参数到指定JavaBean

    List 绑定

    @RequestMapping("/stringlist")
    @ResponseBody
    public String bindStringList (@RequestParam("name") List<String> strs) {
        return "bindStringList:" + strs.toString();
    }
    

    请求:/stringlist?name=Tom&name=Jack
    响应:bindStringList:[Tom, Jack]

    @RequestMapping("/userlist")
    @ResponseBody
    public String bindUserList(UserListForm userListForm){
        return "bindUserList:
    " + usersModel.toString();
    }
    
    public class UserListForm {
        private List<User> list;
        // getters and setters
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (User u : users)
                sb.append(u.toString() + "
    ");
            return sb.toString();
        }
    }
    

    请求:/userlist?users[0].name=Tom&users[2].name=Jack
    响应:
    bindList:
    User [name=Tom, age=null]
    User [name=null, age=null]
    User [name=Jack, age=null]

    PS:tomcat 高版本中[需要转义为%5B]需要转义为%5D

    Set 绑定

    Set 与 List 绑定基本一致,但在使用Set<User>时,需先初始化Set的容量。

    public class UserSetForm {
        private Set<User> users;
        private UserSetForm () {
            // 设置 set 容量为 2 不能访问 size 外的对象
            // 如果覆盖了 User 的 equals 和 hashcode 方法 则 set 容量为 1
            users = new HashSet<User>();
            users.add(new User());
            users.add(new User());
            System.out.println(users.size());
        }
        // getters and setters
        // toString
    }
    
    // User.java
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    

    请求:/userset?users[0].name=Tom
    响应:
    bindUserSet:
    User [name=Tom, age=null]

    错误请求:/userset?users[0].name=Tom&users[1].name=Jack
    错误代码:500
    错误说明:Cannot get element with index 1 from Set of size 1, accessed using property path 'users[1]'

    Map 绑定

    @RequestMapping("/usermap")
    @ResponseBody
    public String bindUserMap (UserMapForm userMapForm) {
        return "bindUserMap:
    " + userMapForm.toString();
    }
    
    public class UserMapForm {
        private Map<String, User> users;
        // getters and setters
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (String s : users.keySet())
                sb.append("Users[" + s + "] = " + users.get(s) + "
    ");
            return sb.toString();
        } 
    }
    

    请求:/usermap?users[x].name=Tom&users[y].name=Jack
    响应:
    bindUserMap:
    Users[x] = User [name=Tom, age=null]
    Users[y] = User [name=Jack, age=null]

    JSON 绑定

    @RequestMapping("/userjson")
    @ResponseBody
    public String bindUserJson (@RequestBody User user) {
        return "bindUserJson:" + user.toString();
    }
    

    请求:
    Content-Type:application/json
    Body:

    {
        "name":"Tom",
        "age":15
    }  
    

    响应:bindUserJson:User [name=Tom, age=15]
    依赖:jackson-databind

    XML 绑定

    @RequestMapping("/userxml")
    @ResponseBody
    public String bindUserXml (@RequestBody User user) {
        return "bindUserXml:" + user.toString();
    }
    
    @XmlRootElement(name="user")
    public class User {   
        private String name;
        private Integer age;
        @XmlElement(name="name")
        public String getName() {
            return name;
        }
        @XmlElement(name="age")
        public Integer getAge() {
            return age;
        }
        // setters
        // toString
    }
    
    

    请求:
    Content-Type:application/xml
    Body:

    <user>
      <name>Tom</name>
      <age>15</age>
    </user> 
    

    响应:bindUserXml:User [name=Tom, age=15]
    依赖:jaxb-api jaxb-impl spring-oxm

    PropertyEditor

    public interface PropertyEditor {
        void setValue(Object value);
        Object getValue();
        String getAsText();
        void setAsText(String text) throws java.lang.IllegalArgumentException;
        // ...
    }
    

    使用:一般使用内置或继承PropertyEditorSupport(implements PropertyEditor),配合WebDataBinder局部使用。

    @RequestMapping("/datepe")
    @ResponseBody
    public String bindDateByPropertyEditor (Date date1) {
        return date1.toString();
    }
    
    @InitBinder("date1")
    public void initDate (WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
    

    请求:/datepe?date1=2019-11-11
    响应:Mon Nov 11 00:00:00 CST 2019

    Formatter

    public interface Formatter<T> extends Printer<T>, Parser<T> {
    
    }
    public interface Printer<T> {
        String print(T object, Locale locale);
    }
    public interface Parser<T> {
        T parse(String text, Locale locale) throws ParseException;
    }
    

    使用:Source 为 String 类型,可全局或局部使用。

    @RequestMapping("/dateformatter")
    @ResponseBody
    public String bindDateByFormatter (Date date2) {
        return date2.toString();
    }
    
    <mvc:annotation-driven conversion-service="formatter"/>
    <!-- conversion-service 与 id 对应 -->
    <bean id="formatter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="org.springframework.format.datetime.DateFormatter">
                    <constructor-arg name="pattern" value="yyyy-MM-dd" />
                </bean>
            </set>
        </property>
    </bean>
    

    请求:/dateformatter?date2=2019-12-12
    响应:Thu Dec 12 00:00:00 CST 2019

    Converter

    public interface Converter<S, T> {
        @Nullable
        T convert(S source);
    }
    

    使用:内置实现为 final 类,不可扩展,可自定义源类型和目的类型,可全局或局部使用。

    @RequestMapping("/dateconverter")
    @ResponseBody
    public String bindDateByConverter (Date date3) {
        return date3.toString();
    }
    
    public class DateConverter implements Converter<String, Date> {
        public Date convert(String source) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            try {
                return format.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    <mvc:annotation-driven conversion-service="converter"/>
    <!-- 自定义 Converter 类 -->
    <bean id="converter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="common.DateConverter" />
            </set>
        </property>
    </bean>
    

    请求:/dateconverter?date3=2019-10-24
    响应:Thu Oct 24 00:00:00 CST 2019





    参考资料:SpringMVC数据绑定入门

  • 相关阅读:
    jQuery教程
    AJAX请求 $.ajax方法的使用
    smarty block_function
    smarty
    位运算版本的交换两数
    提取字符串中的数字
    vue地址插件多级联动自适应 + github地址
    vue插件
    网页title旁边的小图片
    二十三种设计模式[14]
  • 原文地址:https://www.cnblogs.com/JL916/p/11883298.html
Copyright © 2011-2022 走看看