SpringMVC类型转换器、属性编辑器
对于MVC框架,参数绑定一直觉得是很神奇很方便的一个东西,在参数绑定的过程中利用了属性编辑器、类型转换器
参数绑定流程
参数绑定:把请求中的数据,转化成指定类型的对象,交给处理请求的方法
- 请求进入到DisptacherServlet,卸下请求中的数据
- DisptacherServlet将请求中的数据发送给Controller
- 获取Controller需要接收的参数类型,将参数类型和请求数据发送给DataBinder
- DataBinder将参数类型和请求数据再发给TypeConverter,由TypeConverter装配成一个bean
- TypeConverter根据bean中的成员类型,在PropertyEditorRegistry中查找已注册的PropertyEditor
- PropertyEditor将数据setter进bean中的成员
- TypeConverter将装配好的bean返回给DataBinder
- DataBinder将装配bean交给处理请求的方法
在参数绑定的过程TypeConverter和PropertyEditor是最核心的数据转化成对象(非序列化)的过程TypeConverter负责将数据转化成一个beanPropertyEditor负责将数据转化成一个成员字段
属性编辑器
PropertiesEditor负责转化简单对象,因为http请求都是以字符串的形式,所以一般都是根据String来转换springmvc提供了很多默认的属性编辑器,在org.springframework.beans.propertyeditors包中,比如
- CustomBooleanEditor.class,String 转换 Boolean
- CustomCollectionEditor.class,String 转换 Collection
- CustomDateEditor.class,String 转换 Date
- CustomMapEditor.class,String 转换 Map
- CustomNumberEditor.class,String 转换 int、floot、double..
所有的属性编辑器都是继承PropertiesEditorSupport,默认的属性编辑器,Spring在启动的时候会自动加载除此之外,如果要装配的属性没有合适的编辑器,还可以自定义属性编辑器注册了自定义的属性编辑器之后,在CustomEditorConfigurer中注册,应用全局都可以使用这个属性编辑器,因为属性编辑器的工厂是全局作用域的
PropertiesEditor源码分析
PropertiesEditor.java
- public class PropertiesEditor extends PropertyEditorSupport {
- //将String转成指定类型的对象
- @Override
- public void setAsText(String text) throws IllegalArgumentException {
- Properties props = new Properties();//Properties以key-value存值
- if (text != null) {
- try {
- //将String中表示的key=value或key:value信息,转化成Properties
- //key表示bean中字段名称
- //如果要转化成Date,则value是Date,String可以是"date=2012-12-12"的形式(date是字段名)
- props.load(new ByteArrayInputStream(text.getBytes("ISO-8859-1")));
- }
- catch (IOException ex) {
- throw new IllegalArgumentException(
- "Failed to parse [" + text + "] into Properties", ex);
- }
- }
- setValue(props);
- }
- //将old object转化成新object
- @Override
- public void setValue(Object value) {
- if (!(value instanceof Properties) && value instanceof Map) {
- Properties props = new Properties();
- props.putAll((Map<?, ?>) value);
- super.setValue(props);
- }
- else {
- //父类PropertyEditorSupport持有value对象,就是要转化后的对象
- super.setValue(value);
- }
- }
- }
需要注意的是,setAsText通过一定格式的字符串来达到属性编辑的效果,"成员名称=value",或者是"成员名称:value",这样就会把value set到bean的指定成员中了编辑器中最重要的两个方法就是,setAsTest(String)和setValue(value),在这两个方法中完成从String——object,object——object
CustomDateEditor源码分析
CustomDateEditor是Spring的一个默认属性编辑器,负责将String转化成指定格式的Date对象同样他也是继承了PropertiesEditorSupport,重写了setAsTest方法
- public class CustomDateEditor extends PropertyEditorSupport {
- //指定的date格式,如"yyyy-MM-dd"
- private final DateFormat dateFormat;
- //是否允许字符串为空
- private final boolean allowEmpty;
- //严格的日期长度
- private final int exactDateLength;
- public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty) {
- //构造器方法
- }
- public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty, int exactDateLength) {
- //构造器方法
- }
- //String转化成Dtae
- @Override
- public void setAsText(String text) throws IllegalArgumentException {
- //判断字符串是否为空
- if (this.allowEmpty && !StringUtils.hasText(text)) {
- setValue(null);
- }
- //判断字符串长度是否等于exactDateLength
- else if (text != null && this.exactDateLength >= 0 && text.length() != this.exactDateLength) {
- throw new IllegalArgumentException(
- "Could not parse date: it is not exactly" + this.exactDateLength + "characters long");
- }
- else {
- try {
- //将text格式化成Date对象
- setValue(this.dateFormat.parse(text));
- }
- catch (ParseException ex) {
- throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
- }
- }
- }
- //从Date输出String
- @Override
- public String getAsText() {
- Date value = (Date) getValue();
- //返回格式化的String
- return (value != null ? this.dateFormat.format(value) : "");
- }
- }
从CustomDateEditor的源码可以看出,最重要的是重写setAsText方法,先校验下字符串格式符不符合要求,不符合要求就抛出异常,再根据字符串转成指定DateFormat的Date对象
类型转换器
刚刚讲的属性编辑器是用来填充bean中的属性的,类型转换器是负责从数据转换成一个bean所以在转换的过程中,需要属性编辑器帮忙填充属性,那么应该持有一堆属性编辑器(bean有各种各样的属性),那么持有一个PropertyEditorRegistry(一个属性编辑器工厂)就可以了类型转化器的实现不像属性编辑器那么多,主要就是三个
- TypeConverter,类型转换的接口
- TypeConverterSupport,类型转换的实现,持有一个TypeConverterDelegate,具体转换工作交给TypeConverterDelegate完成
- TypeConverterDelegate,类型转换的委托类,所有类型转换的工作都由他完成
要实现的方法就只有convertIfNecessary,从源对象转换为目标对象
TypeConverterDelegate源码分析
因为转换工作是由TypeConverterDelegate负责的,源码太长,就看看转换那一部分的代码
- /*
- @Param propertyName bean的名称
- @Param requiredType 需要的类型
- @Param typeDescriptor 类型描述器
- */
- public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
- //从注册的属性编辑器中获取能编辑requiredType的属性编辑器
- PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
- //...
- //使用属性编辑器去把oldValue转化成requiredType
- convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
- //...
- return convertedValue;
- }
- /*
- @Param propertyName bean的名称
- @Param requiredType 需要的类型
- @Param editor 属性编辑器
- */
- private Object doConvertValue(Object oldValue, Object newValue, Class<?> requiredType, PropertyEditor editor) {
- Object convertedValue = newValue;
- if (editor != null && !(convertedValue instanceof String)) {
- try {
- //转换数据
- editor.setValue(convertedValue);
- //得到转换后的数据
- Object newConvertedValue = editor.getValue();
- if (newConvertedValue != convertedValue) {
- convertedValue = newConvertedValue;
- editor = null;
- }
- }
- catch (Exception ex) {
- if (logger.isDebugEnabled()) {
- logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
- }
- }
- }
- Object returnValue = convertedValue;
- //...
- return returnValue;
- }
- }
SpringMVC类型转换器、属性编辑器的更多相关文章
- springmvc 类型转换器 自定义类型转换器
自定义类型转换器的步骤: 1.定义类型转换器 2.类型转换器的注册(在springmvc配置文件处理) 来解决多种日期格式的问题: springmvc 类型转换器 表单数据填错后返回表单页面(接上面的 ...
- springmvc 类型转换器 数据回显及提示信息
处理器的写法: 类型转换器的写法: 类型转换器在springmvc.xml中的配置如下: index.jsp的写法:
- springmvc——自定义类型转换器
一.什么是springmvc类型转换器? 在我们的ssm框架中,前端传递过来的参数都是字符串,在controller层接收参数的时候springmvc能够帮我们将大部分字符串类型的参数自动转换为我们指 ...
- 属性编辑器,即PropertyEditor-->Spring IoC
在Spring配置文件里,我们往往通过字面值为Bean各种类型的属性提供设置值:不管是double类型还是int类型,在配置文件中都对应字符串类型的字面值.BeanWrapper填充Bean属性时如何 ...
- Spring 学习笔记 数据绑定,校验,BeanWrapper 与属性编辑器
Spring 数据绑定,校验,BeanWrapper,与属性编辑器 Data Binding 数据绑定(Data binding)非常有用,它可以动态把用户输入与应用程序的域模型(或者你用于处理用户输 ...
- 《SpringMVC从入门到放肆》十二、SpringMVC自定义类型转换器
之前的教程,我们都已经学会了如何使用Spring MVC来进行开发,掌握了基本的开发方法,返回不同类型的结果也有了一定的了解,包括返回ModelAndView.返回List.Map等等,这里就包含了传 ...
- SpringMVC源码阅读:属性编辑器、数据绑定
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC自定义类型转换器
SpringMVC 自定义类型转换器 我们在使用SpringMVC时,常常需要把表单中的参数映射到我们对象的属性中,我们可以在默认的spring-servlet.xml加上如下的配置即可做到普通数据 ...
- springMVC注解@initbinder日期类型的属性自动转换
在实际操作中经常会碰到表单中的日期 字符串和Javabean中的日期类型的属性自动转换, 而springMVC默认不支持这个格式的转换,所以必须要手动配置, 自定义数据类型的绑定才能实现这个功能. 一 ...
随机推荐
- Linux学习笔记(一):常用命令
经过统计Linux中能够识别的命令超过3000种,当然常用的命令就远远没有这么多了,按照我的习惯,我把已经学过的Linux常用命令做了以下几个方面的分割: 1.文件处理命令 2.文件搜索命令 3.帮助 ...
- AutoMapper(四)
返回总目录 自定义值解析 虽然AutoMapper覆盖了相当一部分目标成员的映射场景,但是还有 1-5%的目标值需要解析处理一下.很多时候,自定义的值解析是可以放在领域层的领域逻辑.然而,如果该逻辑只 ...
- 写给.NET开发者的数据库Migration方案
微软给我们提供了一种非常好用的数据库迁移方案,但是我发现周围的同学用的并不多,所以我还是想把这个方案整理一下..NET选手看过来,特别是还在通过手工执行脚本来迁移数据库的同学们,当然你也可以选择EF的 ...
- 搞了我一下午竟然是web.config少写了一个点
Safari手机版居然有个这么愚蠢的bug,浪费了我整个下午,使尽浑身解数,国内国外网站搜索解决方案,每一行代码读了又想想了又读如此不知道多少遍,想破脑袋也想不通到底哪里出了问题,结果竟然是web.c ...
- Angular2学习笔记——路由器模型(Router)
Angular2以组件化的视角来看待web应用,使用Angular2开发的web应用,就是一棵组件树.组件大致分为两类:一类是如list.table这种通放之四海而皆准的通用组件,一类是专为业务开发的 ...
- Android,适合Restful网络请求封装
借助volley.Gson类库. 优点 网络请求集中处理,返回值直接为预期的对象,不需要手动反序列,提高效率,使用时建立好model类即可. 使用效果 DataProess.Request(true, ...
- HTML5 <details> 标签
HTML5 中新增的<details>标签允许用户创建一个可展开折叠的元件,让一段文字或标题包含一些隐藏的信息. 用法 一般情况下,details用来对显示在页面的内容做进一步骤解释.其展 ...
- 将一句话里的单词进行倒置,标点符号不倒换。比如将“I come from Shanghai.”倒换后变为“Shanghai. from come I”
string str = "I come from Shanghai."; //根据空格切割 string[] strS = str.Split(' '); string temp ...
- DOM getElementsByClassName IE兼容方案
平时写HTML时多用class来命名,为很少用id来命名,主要原因就是class使用起来比较灵活. 但是万恶的JS在操作DOM的时候对ie6+只提供了getElementById和getElement ...
- ECMASCript2015 提案 stage-3的对象展开运算符
看源码时看到如下的代码 export default { //通过mapActions将actions映射到methods里 methods: { ...mapActions([ 'updateSta ...