spring mvc数据绑定
spring mvc通过反射机制对目标方法的签名进行分析,将请求消息绑定到处理方法入参中。
数据绑定的核心部件是DataBinder。
spring mvc主框架将servletRequest对象及处理方法入参对象实例传递给DataBinder,DataBinder调用装配在spring mvc上下文中的ConversionService组件进行数据类型转换,数据格式化的工作,将servletRequest中的消息填充到入参对象中,然后再调用Validator组件对已绑定了请求消息数据的入参对象进行数据合法性检验,并最终生成数据绑定结果BindingResult对象,BindingResult包含了已完成数据绑定的入参对象,还包含相应的校验错误对象。
数据转换
conversionService是spring类型转换体系的核心接口,位于org.springframework.core.convert包中,可以利用org.springframework.context.support.ConversionServiceFactoryBean在spring上下文中定义一个ConversionSerivce。spring 自动识别出上下文中的ConversionService,并在Bean属性配置及springmvc处理方法入参绑定等场合使用它进行数据的转换。
<bean id="conversionSerivce"
class="org.springframework.context.support.ConversionServiceFactoryBean"/>
该FactoryBean创建ConversionSerivce内建了很多转换器,可通过该FactoryBean的convertors属性注册自定义的类型转换器
<bean id="conversionSerivce"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<propertyname="converters">
<list>
<bean class="xxxxx"/>
</list>
</property>
</bean>
spring 内置3中类型转换器接口,分别是
Converter<S,T>
ConverterFactory<S,R>
GenericConverter
自定义的类型转换器必须实现其中一个
Converter
Converter接口是spring最简单的转换器接口,仅包含一个方法
public interface Converter<S,T>{
Tconverter(S source);//负责将S类型对象转换成T类型对象
}
ConverterFactory<S,R>
ConverterFactory接口定义如下
public interface ConverFactory<S,R>{
<T,R>Converter<S,T> getConverter(Class<T> targetType);
}
S为源类型,R为目标类型的基类,T为扩展于R基类的类型。如spring的stringToNumberConverFactory就实现了ConverterFactory接口,封装了String转换成各种数据类型的Converter
在spring mvc中使用conversionSerivce
<userName>:<password>:<realName>-> User
1、<mvc:annotation-drivenconversion-service="conversionService"/>装配自定义conversionService
<mvc:annotation-driven>该标签可以简化springmvc相关配置,默认情况下,它会创建并注册一个默认的DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter,如果上下文中存在自定义的对应组件bean,spring mvc会自动利用自定义的bean覆盖默认的,除此之外,<mvc:annotation-driven/>标签还会注册一个默认的ConversionService,即FormattingConversionServiceFactoryBean,由于要自定义converter,因此要显示定义一个ConversionSerivce覆盖默认的实现。
2、装配自定义转换器
<bean id="conversionSerivce"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<propertyname="converters">
<list>
<bean class="StringToUserConverter"/>
</list>
</property>
</bean>
3、编写转换器类
public class StringToUserConverter implementsConverter<String,User>{
publicUser convert(String source){
Useruser = new User();
if(source!=null){
Stringitems = source.split(“:”);
user.setUserName(items[0]);
user.setPassword(items[1]);
user.setRealName(items[2]);
}
}
}
@InitBinder
在控制器中使用@InitBinder添加自定义编辑器
@InitBinder
public void initBinder(WebDataBinder binder){
binder.registerCustomEditor(User.class,newUserEditor());
}
spring mvc使用WebDataBinder处理请求消息和处理方法入参的绑定工作,自定义编辑器必须实现PropertyEditor接口。
全局范围自定义编辑器
1、实现WebBindingInitalizer接口
public void initBinder(WebDataBinder binder,WebRequestrequest);
2、在web上下文中通过AnnotationMethodHandlerAdapter装配
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<propertyname="webBindingInitializer">
<bean class="xxx"/>
</property>
</bean>
spring mvc将按以下顺序查找类型转换编辑器
@InitBinder->ConversionService->WebBindingInitializer
数据格式化
spring 使用转换器进行源类型对象到目标类型对象的转换,spring 转换器并不提供输入输出信息格式化工作。
注解驱动格式化
注解驱动重要接口
spring在org.springframework.format包中提供了一个
AnnotationFormatterFactory<A extends Annotation>接口,接口方法如下:
Set<Class<?>> getFieldTypes():表示哪些类可以标注A注解
Parser<?> getParser(A annotation,Class<?>fieldType):根据注解A获取特定类型的Parser
Printer<?> getPrinter(Aannotation,Class<?> fieldType):根据注解A获取特定类型的Printer
spring提供2个内建实现类,分别支持数组及数字类型的注解驱动格式化
NumberFormatAnnotationFormatterFactoryBean:支持数字类型的属性使用(@NumberFormat)
JodaDateTimeFormatAnnotationFormatFactoryBean:用于日期类型(@DateTimeFormat)
启用注解驱动格式化功能
spring中定义了一个实现了ConversionSerivce实现类FormattingConversionService,该类扩展于GenericConversionService,它既有类型转换功能也有格式化功能。
FormattingConversionService也拥有一个FormattingConversionServiceFactoryBean,后者用于在spring上下文中构造一个FormattingConversionSerivce,通过这个类即可以注册自定义转换器,还可以注册自定义注解驱动逻辑。
NumberFormatAnnotationFormatterFactoryBean/JodaDateTimeFormatAnnotationFormatFactory
会自动注册到FormattingConversionServiceFactoryBean中,因此装配该FactoryBean后,就可以在入参绑定及模型数据输出使用注解驱动格式化功能。
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<propertyname="converters">
<list><bean class="xxxx"/></list>
</property>
</bean>
用FormattingConversionServiceFactoryBean替换原来的ConversionServiceFactoryBean
<mvc:annotation-driven/>标签默认创建了FormattingConversionServiceFactoryBean
@DateTimeFormat
可以对Java.util.Date,java.util.Calendar,java.lang.Long,joda时间类型属性标注
@DateTimeFormat(partten=”yyyy-MM-dd”)
@NumberFormat可对数字类型属性标注
@NumberFormat(pattern=”#,###.##”)