spring MVC中数据绑定之日期类型

spring MVC中数据绑定之日期类型

标签: spring mvc数据绑定databind类型转换
  3164人阅读  评论(0)  收藏  举报
  分类:

数据绑定应该算是spring MVC的特点之一吧~简单易用且功能强大,极大地简化了我们编程人员对于用户输入数据的接收及转换。

早先版本的Spring中的数据绑定完全都是基于PropertyEditor的。而Spring3中引入了Converter,用来替代PropertyEditor完成类型转换。

那么我们也依照这个顺序,先来讲讲基于传统的PropertyEditor来实现日期类型的数据绑定。


在Spring MVC中,我们可以通过WebDataBinder来注册自定义的PropertyEditor,从而添加对应的请求参数绑定。有两种方式:

1、使用@InitBinder注解@Controller中的方法 2、自定义WebBindingInitializer来提供一个全局的数据绑定规则。


1、使用@InitBinder注解

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @InitBinder  
  2. public void initBinder(WebDataBinder binder){  
  3.     binder.registerCustomEditor(Date.classnew DateEditor());  
  4. }  

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class DateEditor extends PropertyEditorSupport {  
  2.     @Override  
  3.     public void setAsText(String text) throws IllegalArgumentException {  
  4.         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  5.         Date date = null;  
  6.         try {  
  7.             date = format.parse(text);  
  8.         } catch (ParseException e) {  
  9.             format = new SimpleDateFormat("yyyy-MM-dd");  
  10.             try {  
  11.                 date = format.parse(text);  
  12.             } catch (ParseException e1) {  
  13.                 e1.printStackTrace();  
  14.             }  
  15.         }  
  16.         setValue(date);  
  17.     }  
  18. }  

这里我们将DateEditor提出来封装成一个类方便重用。

另外这里有个try...catch的小妙用,就是首先以"yyyy-MM-dd HH:mm:ss"的形式来解析用户输入的参数,若解析失败则转以"yyyy-MM-dd"的形式来解析。这样的逻辑就可以同时处理"yyyy-MM-dd HH:mm:ss"和"yyyy-MM-dd"形式的日期数据,我想在一般的中文系统中,这两种形式应该是最常用的了吧。

添加如上代码之后,@InitBinder所在的Controller就可以自动绑定日期类型的数据了,不过这仅仅是在该Controller中生效,若想在全局范围内生效的话,可以将@InitBinder注解所在的Controller定义为一个BaseController,其余Controller都继承这个Controller。当然还有另外的方法,若你有兴趣的话,请看2。


2、自定义WebBindingInitializer

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MyWebBindingInitializer implements WebBindingInitializer {  
  2.       
  3.     @Override  
  4.     public void initBinder(WebDataBinder binder, WebRequest request) {  
  5.         binder.registerCustomEditor(Date.classnew DateEditor());  
  6.     }  
  7. }  

还是前面写的DateEditor,这么快又见面了,只不过注册的位置改变了,在WebBindingInitializer中注册的PropertyEditor是在全局范围内共享的。

不过光这样还不够,还要将WebBindingInitializer注入到AnnotationMethodHandlerAdapter中。

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean  
  2.     class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  
  3.     <property name="webBindingInitializer">  
  4.         <bean  
  5.             class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" />  
  6.     </property>  
  7. </bean>  


如果是用<mvc:annotation-driven />的童鞋,上面的配置就没效果了,而mvc命名空间也没提供如此细粒度的配置,怎么办呢?

别怕,方法还是有的,我们可以通过一个自定义PostBeanProcessor来处理:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public Object postProcessBeforeInitialization(Object bean, String beanName)  
  3.         throws BeansException {  
  4.     if (bean instanceof RequestMappingHandlerAdapter) {  
  5.         RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;  
  6.         adapter.setWebBindingInitializer(new MyWebBindingInitializer());  
  7.     }  
  8.     return bean;  
  9. }  

不过实际上<mvc:annotation-driven />默认就为我们提供了一个WebBindingInitializer——ConfigurableWebBindingInitializer

而上面的方法则会覆盖默认的ConfigurableWebBindingInitializer,其实我们可以直接使用这个Bean来注册我们的PropertyEditor:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public Object postProcessBeforeInitialization(Object bean, String beanName)  
  3.         throws BeansException {  
  4.     if(bean instanceof ConfigurableWebBindingInitializer){  
  5.         ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) bean;  
  6.         initializer.setPropertyEditorRegistrar(new PropertyEditorRegistrar() {  
  7.             @Override  
  8.             public void registerCustomEditors(PropertyEditorRegistry registry) {  
  9.                 registry.registerCustomEditor(Date.classnew DateEditor());  
  10.             }  
  11.         });  
  12.     }  
  13.     return bean;  
  14. }  

这里需要说明一下,WebBindingInitializer中不仅仅能注册PropertyEditor,还能注册Converter,也就是下面的3


3、使用ConverstionService

Spring3新引入了Converter系统,而ConversionService则是一个Facade类,用来封装底层实现而对外提供便捷的类型转换。所以这里不能重用之间的DateEditor了,不过大致逻辑还是一样的。另外补充说明一下,Converter是处理任意两类型间的转换,而Formatter是处理字符串和另一类型之间的转换的。可以看出来,Formatter是一类特殊的Converter,并且在处理数据绑定时,Formatter比Converter更加合适。所以我们这里就用Formatter来做:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class DateFormatter implements Formatter<Date> {  
  2.   
  3.     @Override  
  4.     public String print(Date object, Locale locale) {  
  5.         return null;  
  6.     }  
  7.   
  8.     @Override  
  9.     public Date parse(String text, Locale locale) throws ParseException {  
  10.         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  11.         Date date = null;  
  12.         try {  
  13.             date = format.parse(text);  
  14.         } catch (Exception e) {  
  15.             format = new SimpleDateFormat("yyyy-MM-dd");  
  16.             date = format.parse(text);  
  17.         }  
  18.         return date;  
  19.     }  
  20.   
  21. }  

这里我们只写String到Date的逻辑。然后需要将DateFormatter注册到一个ConversionService中,最后再将ConversionService注册到Spring MVC中。

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean id="conversionService"  
  2.     class="org.springframework.format.support.FormattingConversionServiceFactoryBean">  
  3.     <property name="formatters">  
  4.         <set>  
  5.             <bean class="com.test.common.core.DateFormatter"></bean>  
  6.         </set>  
  7.     </property>  
  8. </bean>  


如果是用<mvc:annotation-driven />的童鞋,那么很简单,只需要:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <mvc:annotation-driven conversion-service="conversionService"/>  


而未使用<mvc:annotation-driven />的童鞋,需要定义一个WebBindingInitializer(或者使用ConfigurableWebBindingInitializer),然后注入到RequestMappingHandlerAdapter中去:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean  
  2.     class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  
  3.     <property name="webBindingInitializer" ref="webBindingInitializer">  
  4.     </property>  
  5. </bean>  
  6.   
  7. <bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">  
  8.     <property name="conversionService" ref="conversionService"></property>  
  9. </bean>  

此时可能有人会问,如果同时使用PropertyEditor和ConversionService,执行顺序是什么呢?内部首先查找PropertyEditor进行类型转换,如果没有找到相应的PropertyEditor再通过ConversionService进行转换。


4、PropertyEditor的自动注册

对了,这里再稍带提一下自动注册PropertyEditor,只需要将JavaBean和JavaBean名称+Editor这两个类放在同一包下,那么JavaBeans的基础结构会自动发现PropertyEditor的类,而无需你手动注册~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值