格式化器是将对象转换为特定格式的字符串,其实Java语言已提供了类似的功能,例如java.text.format下面的相关类,最常使用的有SimpleDateFormat和NumberFormat。
格式化器的使用步骤与之前格式化器的步骤基本相同。
- 第一步编写自定义的格式化器,
- 第二步注册格式化器。
格式化器的实现方式有两种,一种是接口方式,一种是注解方式。
1、接口方式
Spring框架使用Printer接口表示将对象转换为特定格式字符串,使用Parser接口表示将特定格式字符串转换为对象。Formatter接口继承Printer接口和Parser接口。
接口形式的实现方式有两个步骤:
- 第一步,编写自定义Formatter接口实现类,其中print方法表示将对象转换为特定字符串,parse方法表示将特定字符串转换为对象
- 第二步,注册,类似于转换器的第二种方式,设置FormattingConversionServiceFactoryBean的formatter属性。
<!-- 注入FormattingConversionServiceFactoryBean,默认的DefaultFormattingConversionService会根据registerDefaultFormatters注入默认的格式化器 --> <bean id="formatService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 配置formatter属性 --> <property name="formatters"> <set> <!-- 自己编写的formatter接口实现类 --> <bean class="com.formatter.XXFormatterImpl" /> </set> </property> </bean>
2、注解方式
注解形式的实现方式有两个步骤:
- 第一步,实现AnnotationFormatterFactory接口,接口上标注有泛型参数,为自定义的注解XXFormatterAnnotation。其中getPrinter方法返回Printer接口的实现类,getParser返回Parser接口的实现类,可以统一返回Formatter接口的实现类。
- 第二步:注册,跟接口形式的注册方式是一样的。
之后直接添加到属性上即可
3、默认注入的格式化器
可以查看DefaultFormattingConversionService的addDefaultFormatters源代码:
public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
// Default handling of number values
formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Default handling of monetary values
if (jsr354Present) {
formatterRegistry.addFormatter(new CurrencyUnitFormatter());
formatterRegistry.addFormatter(new MonetaryAmountFormatter());
formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
}
// Default handling of date-time values
// just handling JSR-310 specific date and time types
new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);
if (jodaTimePresent) {
// handles Joda-specific types as well as Date, Calendar, Long
new JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry);
}
else {
// regular DateFormat-based Date, Calendar, Long converters
new DateFormatterRegistrar().registerFormatters(formatterRegistry);
}
}
大致就是日期和数字相关的Formatter。其实我们在实现转换器时,可以顺便进行格式化,但是这样会导致耦合。
不论是校验,转换,格式化,这些都是数据绑定过程中的一个子功能。