1、SpringMVC主框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象。
2、DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据转换、数据格式化工作。将Servlet中的请求信息填充到入参对象中。
3、调用Validator组件对已经banding了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象。
4、SpringMVC抽取BindingResult中的入参对象和校验错误对象,将它们赋给处理方法的相应入参。
数据转换
SpringMVC上下文中内建了很多转换器,可完成大多数Java类型的转换工作。
ConversionService是Spring类型转换体系的核心接口,可以利用ConversionServiceFactoryBean在Spring的IOC容器中定义一个ConversionService,Spring将自动识别出IOC容器中的ConversionService,并在Bean属性配置SpringMVC处理方法入参绑定等场合使用它进行数据的转换。
可以通过ConversionServiceFactoryBean的converters属性注册自定义类型转换器。 < mvc:annotation-driven>会将自定义的ConversionService注册到SpringMVC的上下文中
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" >
<property name="converters">
<set>
<ref bean="myConverter"/>
</set>
</property>
</bean>
Spring定义了3中类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactoryBean中:
Converters<S,T> :将S类型对象转换为T类型对象
ConverterFactory:将相同系列多个“同质”Converter封装在一起。如果希望将一种类型的对象转换为另一种类型及子类的对象(例如将String转换为Number及Number子类对象)可使用该转换器工厂类。
GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息尽心各类型转换。
mvc:annotation-driven标签
该标签会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter以及ExceptionHandlerExceptionResolver三个bean。()
还会提供以下支持:
支持使用ConversionService实例对表单参数进行类型转换
支持使用@NumberFormatAnnotation、@DataTimeFormat注解完成数据类型的格式化
支持使用@Valid注解对JavaBean实际进行JSR303验证
支持使用@RequestBody和ResponseBody注解
当使用mvc:view-controller标签时一定要加入mvc:annotation-driven,不然会使requestMapping失效。
当为了处理静态资源问题而加入mvc:default-servlet-handler时,也一定要加入mvc:annotation-driven,不然requestMapping同样会失效。
当使用自定义类型转换器的时候需要加上mvc:annotation-driven标签。
@InitBinder
由@InitBinder标识的方法,可以对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成由表单字段到JavaBean属性的绑定。
@InitBinder方法不能有返回值,它必须声明为void。
@InitBinder方法的参数通常是WebDataBinder
数据格式化
如时间类型的属性,界面传入的是String,如何自动转换成时间
首先配置文件中必须添加mvc:annotation-driven注解,同时在POJO属性上添加上
@DateTimeFormat(pattern="yyyy-MM-dd")。
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
//表示界面上输入的是1,234,567.8形式的字符
@NumberFormat(pattern = "#,###,###.#")
private Float salary;
<mvc:annotation-driven></mvc:annotation-driven>
对对象属性的输入输出进行格式化,从本质上讲依然属于“类型转换”的范畴。Spring在格式化模块中定义了一个实现ConversionService接口的FormattingConversionService实现类,该实现类扩展了GenericConversionService,因此它既具有类型转换功能,又具有格式化的功能。
FormattingConversionService拥有一个FormattingConversionServiceFactoryBean工厂类,后者用于在Spring上下文中构造前者。
FormattingConversionServiceFactoryBean内部已经注册了两个Bean:
NumberFormatAnnotationFormatterFactory,用于支持对数字类型属性使用@NumberFormat注解。
JodaDateTimeFormatAnnotationFormatterFactory:支持对日期类型的属性使用@DateTimeFormat注解。
装配了FormattingConversionServiceFactoryBean后,就可以在SpringMVC入参绑定及模型数据输出时使用注解驱动了。mvc:annotation-driven默认创建的ConversionService实例即为FormattingConversionServiceFactoryBean。
如果是使用了自定义数据转换器,其< mvc:annotation-driven>会指定conversion-service属性,这时需要将其配置的ConversionService的class设置成FormattingConversionServiceFactoryBean,这样既可以使用数据转换,也可以进行数据格式化
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" >
<property name="converters">
<set>
<ref bean="myConverter"/>
</set>
</property>
</bean>
当数据转换失败或格式化属性失败时,SpringMVC会将错误信息放入BindingResult中,那么可以在目标方法的入参中传入BindingResult,在方法中可以获取错误信息。
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("user111")User user,BindingResult result) {
if(result.hasFieldErrors()) {
System.out.println(result.getFieldErrors());
}
System.out.println("修改User : "+ user);
return SUCCESS;
}