前边我们讲过了如何视图和视图解析器,重定向,访问静态资源。下边我们来讲一讲SpringMVC是如何控制一个表单数据绑定包目标方法的入参上的。
可以预想到,表单数据本身是一个String型的数据,而目标方法中的入参却是一个POJO类对象的属性,可能是Date也可能是Number,那么从String到Date类型的转化过程中,可能涉及到类型转化、格式化、数据逻辑校验等问题。
1.数据绑定流程
①SpringMVC将ServletRequest和目标方法的入参传递给WebDataBindingFactoryBean对象,以创建DataBinder实例对象。
② DataBinder调用装配在Spring上下文当中的ConverterService组件来进行数据转换和格式化工作。并将请求信息传递入参对象中。
③ 调用Validator组件对已绑定了请求信息的入参对象进行数据逻辑合法性的验证,并最终生成数据绑定结果BindingData对象。
④ SPringMVC抽取BindingData中的入参对象和校验错误对象,将他们赋值给处理方法的相应入参。
2.自定义类型转换器
大部分情况下,SpringMVC的内置转换器就已经足够程序的运行,不需要再自定义转换器。
自定义转换器的步骤
① 写一个实现了Converter<S,T>接口的实现类,并重写convert方法。
② 在spring的配置文件中注册一个ConversionServiceFactoryBean,并在其中指明属性converters为自定义转换器的类名。
③ 然后在<mvc:annotation-driver conversion-service=””>属性中指明使用的转换服务为②中的bean的ID即可。
3.数据的格式化
我们需要用户在输入表单的日期格式和数字格式方面进行限定,所以我们采用在POJO类的属性上进行标注注解@DateTimeFormat(partern="yyyymmdd")和@NumberFormat(partern="#,###,###.#" 数字用#来代替)来限定。
需要注意的是,SpringMVC默认的ConversionService是DefaultFormatConversionService,我们在前边希望使用自定的转换器的时候讲到要用ConversionServiceFactoryBean来注册那个自定义的转换器到转换服务中去,但是若希望同时SpringMVC提供的类型转换器也起作用,就需要使用FormattingConversionServiceFactoryBean来注册了。
4.数据的校验
数据的校验就是指我们需要对表单的输入数据的逻辑上进行验证,如生日必须要小于当前日期,等待。
在SpringMVC中使用JRS303作为数据合法性校验的标准框架,JSR通过在Bean的属性上添加类似于@NotNull、@Max等注解的方式来指定对表单输入的验证规则,并通过标准的验证接口对Bean进行验证。
具体的,我们使用Hibernate Validator这个实现了JSR303标准的框架来对POJO类的属性进行注解,它除了支持JSR303的注解之外,还支持诸如@Email、@NotEmpty等注解。
使用Hibernate Validator的步骤
① 导入JSR303的三个jar包,同时将对应的三个el包放在Tomcat下并删除原el.jar包
② 在spring的配置文件中加上<mvc:annotation-driver />,这样他才会JSR303验证
③ 在相应的POJO类的属性上添加校验注解类型。
④ 在目标方法的入参前添加@validat属性,这样SpringMVC在完成数据绑定后就会针对这个POJO属性进行数据逻辑的验证了。
需要注意的是,我们可以在目标方法的入参中添加一个@BindingResult注解来注解BindingResult类型的变量,这样就可以通着这个变量获取到格式验证或者校验失败的信息,但是@validat和@BindResult二者标注的属性必须紧邻,因为前者的验证结果对象放入到了BindingReslt中了。
5 错误消息的显示和国际化
我们在目标页面中使用<form:errors path="" />来获取BindingResult中的错误消息,如格式不正确,校验逻辑失败等。数据校验结果即时未对目标方法入参进行注入也会放入到隐含模型中,最终放入到Request中以供目标页面获取。
当SpringMVC标签显示错误消息时,SpringMVC会查看WEB上下文是否装配了对应国际化信息,若无则显示默认错误消息,有则显示国际化错误消息。
国际化步骤
① 配置i18n.properties国际化资源文件,其中的key的格式是:ValidateName.Map中的key.对象的实例名称,例如:Max.employee.lastName。
② 在spring.xml中将国际化资源文件加载到上下文中,使用ResourceBundleMessageSource来配置一个bean。