Spring MVC会根据请求方法签名不一样,将请求息消息中的信息以必定的方式转换并绑定到请求方法的参数中。在请求消息到达真正调用处理方法的这一段时间内,Spring MVC还会完成不少其余的工做,包括请求信息转换、数据转换、数据格式化以及数据校验等。
Spring MVC经过反射机制对目标处理方法的签名进行分析,并将请求消息绑定处处理方法的参数中。数据绑定的核心部件是DateBinder
,其运行机制以下图:java
Spring MVC框架将Servlet对象及处理方法的参数对象实例传递给DataBinder,它会调用装配在Spring Web上下文中的ConversionService组件进行数据类型转换、数据格式化工做,并将ServletRequest中的消息填充到参数对象中。而后在调用Validator组件对已经绑定了请求消息数据的参数对象进行数据合法性校验,并最终生成数据绑定结果BindingResult对象。BindingResult包含已完成数据绑定的参数对象,还包含相应的校验错误对象,Spring MVC抽取BindingResult中的参数对象以及校验错误对象,将它们赋给处理方法的相应参数。web
org.springframework.core.convert.ConversionService是Spring类型转换体系的核心接口,在该接口中定义了如下4个方法:spring
判断是否能够将一个Java类转换为另外一个Java类.数组
须要转换的类将以成员变量的方式出现,TypeDescriptor不但描述了须要转换类的信息,还描述了类的上下文信息,例如成员变量上的注解成员变量是否以数组、集合或者Map的方式呈现。类型转换逻辑能够利用这些信息作出各类灵活的控制。mvc
将原类型对象转换为目标类型对象。app
将对象从源类型对象转换为目标类型对象,一般会利用到类中的上下文信息。框架
能够利用org.springframework.context.support.ConversionServiceFactoryBean在Spring的上下文中定义一个ConversionService。Spring将自动识别出上下文中的ConversionService,并在Spring MVC处理方法的参数绑定中使用它进行数据转换。示例以下:编辑器
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"></bean>
Spring在org.springframework.core.convert.converter包中定义了三种类型的转换器接口,咱们能够实现其中任意一个,并将它们做为自定义转换器注册到ConversionServiceFactoryBean当中。这三种类型的转换器接口以下所示:
T convert(S var1)
该方法负责将S类型的对象转换为T类型的对象.ide
<T extends R> Converter<S, T> getConverter(Class<T> var1);
S为转换的源类型,R为目标类型的基类,T为R的子类。this
ConvertiblePair封装了源类型和目标类型,而TypeDescriptor包含了须要转换的类型对象的上下文信息,所以GenericConverter接口的convert()方法能够利用这些上下文信息进行类型转换的工做。
代码以下:
public class String2DateConverter implements Converter<String, Date>{ // 日期类型模版 private String datePattern; public void setDatePattern(String datePattern) { this.datePattern = datePattern; } // Converter<S,T>接口的类型转换方法 public Date convert(String s) { try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.datePattern); return simpleDateFormat.parse(s); } catch (Exception e) { e.printStackTrace(); System.out.println("日期转换失败!"); return null; } } }
在springmvc-config.xml中加入自定义字符转换器:
<!--装配自定义的类型转换器--> <mvc:annotation-driven conversion-service="conversionService"/> <!--自定义类型转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.ccgogoing.javaee.converter.String2DateConverter" p:datePattern="yyyy-MM-dd"/> </list> </property> </bean>
在mvc配置文件中,使用了<mvc:annotation-driven/>
标签,该标签能够简化SpringMVC相关配置,自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个bean,这是springMVC为@Controller分发请求所必须的。<mvc:annotation-driven/>
标签还会注册一个默认的ConversionService,即FormattingConversionServiceFactoryBean转换类,所以须要显式定义一个ConversionService覆盖默认实现类;
// 自定义属性编辑器 public class DateEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = simpleDateFormat.parse(text); setValue(date); } catch (ParseException e) { e.printStackTrace(); } } }
// 在控制器初始化时注册属性编辑器 @InitBinder public void initBinder(WebDataBinder binder) { // 注册自定义编辑器 binder.registerCustomEditor(Date.class, new DateEditor()); }
在UserController中增长一个initBinder方法,并使用@InitBinder注解,该注解会在控制器初始化时注册属性编辑器。WebDataBinder对象用于处理请求消息和处理方法的绑定工做.binder.registerCustomEditor
方法将传入的Date类型使用DateEditer类进行转换.
public class DateWebBingdingInitizlizer implements WebBindingInitializer { public void initBinder(WebDataBinder webDataBinder, WebRequest webRequest) { // 注册自定义编辑器 webDataBinder.registerCustomEditor(Date.class,new DateEditor()); } }
DateWebBingdingInitizlizer类实现WebBindingInitializer接口,并在initBinder()方法中注册自定义编辑器DateEditor类.
UserController类中不须要在使用@InitBinder 注解注释的方法,而是在springmvc-config.xml配置文件中配置全局的自定义编辑器:
<!--经过AnnotationMethodHandlerAdapter装配自定义编辑器--> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="webBindingInitializer"> <bean class="com.ccgogoing.javaee.binding.DateWebBingdingInitizlizer"/> </property> </bean>