SpringMVC 数据绑定

这是我在 慕课网 观看 SpringMVC 数据绑定入门 所做的学习笔记
其中包含对 **List,Set,Map,JSON,XML 的数据绑定以及 PropertyEditor、Formatter、Converter 三种自定义类型转换器 **

  • List 类型绑定

    • 特点

      • List 对象绑定需要建立一个 List 集合包装类
      public class User {
          private int age;
          private String name;
          // 省略 setter getter
      }
      public class ListUserWrap {
          private List<User> userList;
          // 省略 setter getter
      }
      
      • List 的长度为前台传入的 ** 集合最大下标加 1**
      @ResponseBody
      @RequestMapping(value = "/list2")
      public String list2(ListUserWrap listUserWrap) {
          return "listUserWrapSize:" + listUserWrap.getUserList().size() + "\tlistUserWrap:" + listUserWrap;
      }
      
    • 测试数据

      http://localhost/list2?userList[0].name=a&userList[1].name=b
      listUserWrapSize:2 listUserWrap:ListUserWrap(userList=[User(age=0, name=a), User(age=0, name=b)])
      http://localhost/list2?userList[0].name=a&userList[1].name=b&userList[3].name=c
      listUserWrapSize:4 listUserWrap:ListUserWrap(userList=[User(age=0, name=a), User(age=0, name=b), User(age=0, name=null), User(age=0, name=c)])

  • Set 类型绑定

    • 特点

      • Set 对象绑定需要建立一个 Set 集合包装类
      • 需要先定义 Set 集合长度, 并且前台传过来的 Set 长度不能越界, 否者报错
      • ** 设置 Set 长度时需要注意重写对象的 hashCode,equals 方法, 否者后面的会掩盖前面的 **
      public class SetUserWrap {
          private Set<User> userSet;
          // 省略 setter getter
          public SetUserWrap() {
              userSet = new LinkedHashSet<>();
              userSet.add(new User());
              User user = new User();
              user.setName("b");
              userSet.add(user);
          }
      }
      
    • 测试数据

      http://localhost/set?userSet[0].name=a 因为预先定义的第二个对象的 name 为 b, 所以此处返回 b
      setUserWrapSize:2 setUserWrap:SetUserWrap(userSet=[User(age=0, name=a), User(age=0, name=b)])
      http://localhost/set?userSet[0].name=a&userSet[1].name=bbb
      setUserWrapSize:2 setUserWrap:SetUserWrap(userSet=[User(age=0, name=a), User(age=0, name=bbb)])

  • Map 类型绑定

    • 特点

      • 建立一个 Map 包装类
      public class MapUserWrap {
          private Map<String, User> userMap;
          // 省略 setter getter
      }
      @ResponseBody
      @RequestMapping(value = "/map")
      public String map(MapUserWrap mapUserWrap) {
          return "mapUserWrapSize:" + mapUserWrap.getUserMap().size() + "\tmapUserWrap:" + mapUserWrap;
      }
      
    • 测试数据

      http://localhost/map?userMap["a"].name=a&userMap["b"].name=b
      mapUserWrapSize:2 mapUserWrap:MapUserWrap(userMap={a=User(age=0, name=a), b=User(age=0, name=b)})
      http://localhost/map?userMap["a"].name=a&userMap["a"].name=b
      mapUserWrapSize:1 mapUserWrap:MapUserWrap(userMap={a=User(age=0, name=a,b)})

  • JSON 类型绑定

    • 前台在 body 区域传入以下类型格式字符串
    {
        "name":"a",
        "age":1
    }
    
    @ResponseBody
    @RequestMapping(value = "/json")
    public String json(@RequestBody User user) {
        return user.toString();
    }
    
  • XML 类型绑定

    • 前台在 body 区域传入以下类型格式字符串
    <xmluser>
        <name>a</name>
        <age>1</age>
    </xmluser>
    
    • 建立一个 XML 包装类
    @XmlRootElement(name = "xmluser")// 根节点标签名
    public class XmlUser {
        @XmlElement(name = "name")// 属性标签名
        private String name;
        @XmlElement(name = "age")// 属性标签名
        private int age;
    }
    
    @ResponseBody
    @RequestMapping(value = "/xml")
    public String xml(@RequestBody XmlUser xmlUser) {
        return xmlUser.toString();
    }
    
  • 自定义类型转换 - PropertyEditor

    在 Controller 中编写一个带有 InitBinder 注解的方法, 传入 WebDataBinder 对象, 使用该对象注册指定类型的转换关系, 对该方法所在 Controller 中使用该类型的方法参数有效

    @ResponseBody
    @RequestMapping(value = "/date")
    public String date(Date date) {
        return date.toLocaleString();
    }
    @ResponseBody
    @RequestMapping(value = "/date2")
    public String date2(Date date2) {
        return date2.toLocaleString();
    }
    
    @InitBinder("date")// 指定对变量名为 date 进行转换, 不会对 date2 生效
    private void initDate(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
        //binder.registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor)
        //new CustomDateEditor(DateFormat dateFormat, boolean allowEmpty)
        //allowEmpty 是否允许 Date 对象为空
    }
    
  • 自定义类型转换 - Formatter

    根据 String 类型自定义转换规则转换成需要的类型, 需要实现 org.springframework.format.Formatter<T> 接口,T 为想要转换的结果类型

    • 创建自定义 Formatter
    public class DateFormatter implements Formatter<Date> {
        @Override
        public Date parse(String text, Locale locale) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date = null;
            try {
                date = dateFormat.parse(text);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    
        @Override
        public String print(Date object, Locale locale) {
            return null;
        }
    }
    
    • 将自定义的 Formatter 注入到 SpringMVC 默认的 FormattingConversionServiceFactoryBean 中, 同时将默认转换规则服务类配置为已经被注入的 bean 对象
    <mvc:annotation-driven conversion-service="myFormattingConversionService"/>
    <bean id="myFormattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">,<!-- 此处为 formatters-->
            <set>
                <bean class="{包路径}.DateFormatter"></bean>
            </set>
        </property>
    </bean>
    
  • 自定义类型转换 - Converter

    自己指定数据来源类型及转换结果类型, 相比 Formatter 更为灵活, 需要实现 org.springframework.core.convert.converter.Converter<S, T> 接口,S 为来源类型,T 为结果类型

    • 创建自定义 Converter
    public class DateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String source) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date = null;
            try {
                date = dateFormat.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    
    • 将自定义的 Converter 注入到 SpringMVC 默认的 FormattingConversionServiceFactoryBean 中, 同时将默认转换规则服务类配置为已经被注入的 bean 对象
    <mvc:annotation-driven conversion-service="myFormattingConversionService"/>
    <bean id="myFormattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters"><!-- 此处为 converters-->
            <set>
                <bean class="{包路径}.DateConverter"></bean>
            </set>
        </property>
    </bean>
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 基本类型 请求: /baseType?age=2结果: age:20 数组 请求: /array?name=tom...
    缓慢移动的蜗牛阅读 349评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,497评论 18 399
  • 打破惯性防卫-绿灯思维 什么是习惯性防卫 这是一种非常常见的心理学现象。当我们感到自己的观点、尊严可能会受到挑...
    金勇Maya阅读 432评论 0 2
  • 在东方天际泛起鱼肚白之前 一片瑰丽的红霞悄悄地 夹在五六点钟的晨光缝隙间 短暂、多变、不可描摹
    鹅笼书生_阅读 219评论 0 0