自定义数据绑定
一般情况下,使用基本数据类型和POJO类型的参数数据已经能够满足需求,然而有些特殊类型的参数是无法在后台进行直接转换的,例如日期数据就需要开发者自定义转换器(Converter)或格式化(Formatter)来进行数据绑定。
1.Converter
Spring框架提供了一个Converter用于将一种类型的对象转换为另一种类型的对象。例如,用户输入的日期形式可能是“2017-04-08”或“2017/04/08”的字符串,而要Spring将输入的日期与后台的Date进行绑定,则需要将字符串转换为日期,此时就可以自定义一个Converter类来进行日期转换。
自定义Converter类需要实现org.springframework.core.convert.converter.Converter接口,该接口的代码如下所示:
public interface Converter<S, T> {
T convert(S source);
}
在上述接口代码中,泛型中的S表示源类型,T表示目标类型,而convert(S source)表示接口中的方法。
在src目录下,创建一个com.itheima.convert包,在该包下创建日期转换类DateConverter,并在该类中编写将String类型转换成Date类型的代码,如文件1所示。
文件1 DateConverter.java
1 package com.itheima.convert;
2 import java.text.ParseException;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import org.springframework.core.convert.converter.Converter;
6 /**
7 * 自定义日期转换器
8 */
9 public class DateConverter implements Converter<String, Date> {
10 // 定义日期格式
11 private String datePattern = "yyyy-MM-dd HH:mm:ss";
12 @Override
13 public Date convert(String source) {
14 // 格式化日期
15 SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
16 try {
17 return sdf.parse(source);
18 } catch (ParseException e) {
19 throw new IllegalArgumentException(
20 "无效的日期格式,请使用这种格式:"+datePattern);
21 }
22 }
23 }
在上述代码中,DateConverte类实现了Converter接口,该接口中第一个类型String表示需要被转换的数据类型,第二个类型Date表示需要转换成的目标类型。
为了让Spring MVC知道并使用这个转换器类,还需要在其配置文件中编写一个id为conversionService的Bean,如文件2所示。
文件2 springmvc-config.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:mvc="http://www.springframework.org/schema/mvc"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
8 http://www.springframework.org/schema/mvc
9 http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
10 http://www.springframework.org/schema/context
11 http://www.springframework.org/schema/context/spring-context-4.3.xsd">
12 <!-- 定义组件扫描器,指定需要扫描的包 -->
13 <context:component-scan base-package="com.itheima.controller" />
14 <!-- 定义视图解析器 -->
15 <bean id="viewResolver" class=
16 "org.springframework.web.servlet.view.InternalResourceViewResolver">
17 <!-- 设置前缀 -->
18 <property name="prefix" value="/WEB-INF/jsp/" />
19 <!-- 设置后缀 -->
20 <property name="suffix" value=".jsp" />
21 </bean>
22 <!-- 显示的装配自定义类型转换器 -->
23 <mvc:annotation-driven conversion-service="conversionService" />
24 <!-- 自定义类型转换器配置 -->
25 <bean id="conversionService" class=
26 "org.springframework.context.support.ConversionServiceFactoryBean">
27 <property name="converters">
28 <set>
29 <bean class="com.itheima.convert.DateConverter" />
30 </set>
31 </property>
32 </bean>
33 </beans>
在文件2中,首先添加了3个mvc的schema信息;然后定义了组件扫描器和视图解析器;接下来显示的装配了自定义的类型转换器;最后编写了自定义类型转换器的配置,其中Bean的类名称必须为org.springframework.context.support.ConversionServiceFactoryBean,并且Bean中还需要包含一个converters属性,通过该属性列出程序中自定义的所有Converter。
为了测试转换器类的使用,可以在com.itheima.controller包中创建一个日期控制器类DateController,并在类中编写绑定日期数据的方法,如文件3所示。
文件3 DateController.java
1 package com.itheima.controller;
2 import java.util.Date;
3 import org.springframework.stereotype.Controller;
4 import org.springframework.web.bind.annotation.RequestMapping;
5 /**
6 * 日期控制器类
7 */
8 @Controller
9 public class DateController {
10 /**
11 * 使用自定义类型数据绑定日期数据
12 */
13 @RequestMapping("/customDate")
14 public String CustomDate(Date date) {
15 System.out.println("date="+date);
16 return "success";
17 }
18 }
此时,如果发布项目并启动Tomcat服务器,在浏览器中访问地址http://localhost:8080/chapter13/customDate?date= 2017-04-12 15:55:55
(注意日期数据中的空格),控制台的打印信息如图1所示。
图1 运行结果
从图1可以看出,使用自定义类型转换器已从请求中正确获取到了日期信息,这就是自定义数据绑定。
2.Formatter
除了使用Converter进行转换外,我们还可以使用Formatter来进行类型转换。Formatter与Converter的作用相同,只是Formatter的源类型必须是一个String类型,而Converter可以是任意类型。
使用Formatter自定义转换器类需要实现org.springframework.format.Formatter接口,该接口的代码如下所示。
public interface Formatter<T> extends Printer<T>, Parser<T> {}
在上述代码中,Formatter接口继承了Printer和Parser接口,其泛型T表示输入字符串要转换的目标类型。在Printer和Parser接口中,分别包含一个print()和parse()方法,所有的实现类必须覆盖这两个方法。
在com.itheima.convert包中,创建日期转换类DateFormatter,在该类中使用Formatter自定义日期转换器,如文件4所示。
文件4 DateFormatter.java
1 package com.itheima.convert;
2 import java.text.ParseException;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import java.util.Locale;
6 import org.springframework.format.Formatter;
7 /**
8 * 使用Formatter自定义日期转换器
9 */
10 public class DateFormatter implements Formatter<Date>{
11 // 定义日期格式
12 String datePattern = "yyyy-MM-dd HH:mm:ss";
13 // 声明SimpleDateFormat对象
14 private SimpleDateFormat simpleDateFormat;
15 @Override
16 public String print(Date date, Locale locale) {
17 return new SimpleDateFormat().format(date);
18 }
19 @Override
20 public Date parse(String source, Locale locale) throws ParseException
21 {
22 simpleDateFormat = new SimpleDateFormat(datePattern);
23 return simpleDateFormat.parse(source);
24 }
25 }
在文件4中,DateFormatter类实现了Formatter接口,并实现了接口中的两个方法。其中print()方法会返回目标对象的字符串,而parse()方法会利用指定的Locale将一个String解析成目标类型。
要使用Formatter自定义的日期转换器,同样需要在Spring MVC的配置文件中进行注册,其配置代码如下所示。
<!-- 自定义类型格式化转换器配置 -->
<bean id="conversionService" class="org.springframework.format.support.
FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="com.itheima.convert.DateFormatter" />
</set>
</property>
</bean>
与注册Converter类有所不同的是,注册自定义的Formatter转换器类时,Bean的类名必须是org.springframework.format.support.FormattingConversionServiceFactoryBean,并且其属性为formatters。
完成后,通过地址http://localhost:8080/chapter13/customDate?date= 2017-04-12 15:55:55
即可查看实现的效果。由于与图12的显示结果相同,这里不再做演示,读者可自行测试。