格式化器是将对象转换为特定格式的字符串,其实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。其实我们在实现转换器时,可以顺便进行格式化,但是这样会导致耦合。
不论是校验,转换,格式化,这些都是数据绑定过程中的一个子功能。