sPR ing MVC中數據綁定之日期類型 標簽: spring mvc數據綁定databind類型轉換2015-01-29 12:30 3164人閱讀 評論(0) 收藏 舉報 分類:J2EE(41) 版權聲明:本文為博主原創文章,未經博主允許不得轉載。
數據綁定應該算是spring MVC的特點之一吧~簡單易用且功能強大,極大地簡化了我們編程人員對于用戶輸入數據的接收及轉換。
早先版本的Spring中的數據綁定完全都是基于PropertyEditor的。而Spring3中引入了Converter,用來替代PropertyEditor完成類型轉換。
那么我們也依照這個順序,先來講講基于傳統的PropertyEditor來實現日期類型的數據綁定。
在Spring MVC中,我們可以通過WebDataBinder來注冊自定義的PropertyEditor,從而添加對應的請求參數綁定。有兩種方式:
1、使用@InitBinder注解@Controller中的方法 2、自定義WebBindingInitializer來提供一個全局的數據綁定規則。
1、使用@InitBinder注解
[java ] view plain copy @InitBinder public void initBinder(WebDataBinder binder){ binder.registerCustomEditor(Date.class, new DateEditor()); }
[java] view%20plain copy public class DateEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = null; try { date = format.parse(text); } catch (ParseException e) { format = new SimpleDateFormat("yyyy-MM-dd"); try { date = format.parse(text); } catch (ParseException e1) { e1.printStackTrace(); } } setValue(date); } }
這里我們將DateEditor提出來封裝成一個類方便重用。
另外這里有個try...catch的小妙用,就是首先以"yyyy-MM-dd%20HH:mm:ss"的形式來解析用戶輸入的參數,若解析失敗則轉以"yyyy-MM-dd"的形式來解析。這樣的邏輯就可以同時處理"yyyy-MM-dd%20HH:mm:ss"和"yyyy-MM-dd"形式的日期數據,我想在一般的中文系統中,這兩種形式應該是最常用的了吧。
添加如上代碼之后,@InitBinder所在的Controller就可以自動綁定日期類型的數據了,不過這僅僅是在該Controller中生效,若想在全局范圍內生效的話,可以將@InitBinder注解所在的Controller定義為一個BaseController,其余Controller都繼承這個Controller。當然還有另外的方法,若你有興趣的話,請看2。
2、自定義WebBindingInitializer
[java] view%20plain copy public class MyWebBindingInitializer implements WebBindingInitializer { @Override public void initBinder(WebDataBinder binder, WebRequest request) { binder.registerCustomEditor(Date.class, new DateEditor()); } }
還是前面寫的DateEditor,這么快又見面了,只不過注冊的位置改變了,在WebBindingInitializer中注冊的PropertyEditor是在全局范圍內共享的。
不過光這樣還不夠,還要將WebBindingInitializer注入 到AnnotationMethodHandlerAdapter中。
[html] view%20plain copy <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer"> <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" /> </property> </bean>
如果是用<mvc:annotation-driven%20/>的童鞋,上面的配置就沒效果了,而mvc命名空間也沒提供如此細粒度的配置,怎么辦呢?
別怕,方法還是有的,我們可以通過一個自定義PostBeanProcessor來處理:
[java] view%20plain copy @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RequestMappingHandlerAdapter) { RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean; adapter.setWebBindingInitializer(new MyWebBindingInitializer()); } return bean; }
不過實際上<mvc:annotation-driven%20/>默認就為我們提供了一個WebBindingInitializer——ConfigurableWebBindingInitializer
而上面的方法則會覆蓋默認的ConfigurableWebBindingInitializer,其實我們可以直接使用這個Bean來注冊我們的PropertyEditor:
[java] view%20plain copy @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof ConfigurableWebBindingInitializer){ ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) bean; initializer.setPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Date.class, new DateEditor()); } }); } return bean; }
這里需要說明一下,WebBindingInitializer中不僅僅能注冊PropertyEditor,還能注冊Converter,也就是下面的3
3、使用ConverstionService
Spring3新引入了Converter系統,而ConversionService則是一個Facade類,用來封裝底層實現而對外提供便捷的類型轉換。所以這里不能重用之間的DateEditor了,不過大致邏輯還是一樣的。另外補充說明一下,Converter是處理任意兩類型間的轉換,而Formatter是處理字符串和另一類型之間的轉換的??梢钥闯鰜恚現ormatter是一類特殊的Converter,并且在處理數據綁定時,Formatter比Converter更加合適。所以我們這里就用Formatter來做:
[java] view%20plain copy public class DateFormatter implements Formatter<Date> { @Override public String print(Date object, Locale locale) { return null; } @Override public Date parse(String text, Locale locale) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = null; try { date = format.parse(text); } catch (Exception e) { format = new SimpleDateFormat("yyyy-MM-dd"); date = format.parse(text); } return date; } }
這里我們只寫String到Date的邏輯。然后需要將DateFormatter注冊到一個ConversionService中,最后再將ConversionService注冊到Spring%20MVC中。
[html] view%20plain copy <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="com.test.common.core.DateFormatter"></bean> </set> </property> </bean>
如果是用<mvc:annotation-driven%20/>的童鞋,那么很簡單,只需要:
[html] view%20plain copy <mvc:annotation-driven conversion-service="conversionService"/>
而未使用<mvc:annotation-driven%20/>的童鞋,需要定義一個WebBindingInitializer(或者使用ConfigurableWebBindingInitializer),然后注入到RequestMappingHandlerAdapter中去:
[html] view%20plain copy <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="webBindingInitializer"> </property> </bean> <bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService"></property> </bean>
此時可能有人會問,如果同時使用PropertyEditor和ConversionService,執行順序是什么呢?內部首先查找PropertyEditor進行類型轉換,如果沒有找到相應的PropertyEditor再通過ConversionService進行轉換。
4、PropertyEditor的自動注冊
對了,這里再稍帶提一下自動注冊PropertyEditor,只需要將JavaBean和JavaBean名稱+Editor這兩個類放在同一包下,那么JavaBeans的基礎結構會自動發現PropertyEditor的類,而無需你手動注冊~