当前位置: 首页 > 科技观察

Spring中字段格式化详解

时间:2023-03-13 07:14:33 科技观察

环境:Spring5.3.12.RELEASE。Spring提供的一个core.convert包是一个通用的类型转换系统。它提供了一个统一的ConversionServiceAPI和一个强类型的ConverterSPI,用于实现从一种类型到另一种类型的转换逻辑。Spring容器使用这个系统来绑定bean属性值。此外,Spring表达式语言(SpEL)和DataBinder都使用该系统来绑定字段值。例如,当SpEL需要将Short转换为Long以完成表达式时。setValue(objectbean,objectvalue)尝试,核心。转换系统执行转换。现在考虑典型客户端环境(例如Web或桌面应用程序)的类型转换需求。在这种环境中,通常从String转换为支持客户端回发过程,然后再转换回String以支持视图渲染过程。此外,您经常需要本地化String值。更通用的core.convertConverterSPI不直接解决这些格式要求。为了直接解决这些问题,Spring3引入了一个方便的FormatterSPI,它为客户端环境的PropertyEditor实现提供了一个简单而健壮的替代方案。通常,当您需要实现常见的类型转换逻辑时,您可以使用ConverterSPI,例如,java.util.Date和Long之间的转换。当您在客户端环境(例如Web应用程序)中工作并且需要解析和打印本地化的字段值时,您可以使用FormatterSPI。ConversionService为这两个spi提供了统一的类型转换API。1.FormatterSPI实现字段格式化逻辑的FormatterSPI简单且强类型。以下清单显示了Formatter接口定义:packageorg.springframework.format;publicinterfaceFormatterextendsPrinter,Parser{}Formatter继承自Printer和Parser接口。@FunctionalInterfacepublicinterfacePrinter{Stringprint(Tobject,Localelocale);}@FunctionalInterfacepublicinterfaceParser{Tparse(Stringtext,Localelocale)throwsParseException;}默认情况下,Spring容器提供了几个Formatter实现.Number包提供了NumberStyleFormatter、CurrencyStyleFormatter和PercentStyleFormatter以使用java.text.NumberFormat格式化数字对象。datetime包提供了一个DateFormatter来使用java.text.DateFormat格式化java.util.Date对象。自定义格式化程序。publicclassStringToNumberFormatterimplementsFormatter{@OverridepublicStringprint(Numberobject,Localelocale){返回“结果是:”+object.toString();}@OverridepublicNumberparse(Stringtext,Localelocale)throwsParseException{returnNumberFormat.getInstance().parse(text);}}如何使用?我们可以通过FormattingConversionService转换服务添加自定义格式化类。FormattingConversionServicefcs=newFormattingConversionService();//默认如果不添加自定义的格式化类,那么程序运行将报错fcs.addFormatterForFieldType(Number.class,newStringToNumberFormatter());Numbernumber=fcs0.convert(",Number.class);System.out.println(number);查看源代码:publicclassFormattingConversionServiceextendsGenericConversionServiceimplementsFormatterRegistry,EmbeddedValueResolverAware{publicvoidaddFormatterForFieldType(ClassfieldType,Formatterformatter){addConverter(newPrinterConverter(fieldType,formatter,this));addConverter(newParserConverter(fieldType,formatter,this));}privatestaticclassPrinterConverterimplementsGenericConverter{}privatestaticclassParserConverterimplementsGenericConverter{}}publicclassGenericConversionServiceimplementsConfigurableConversionService{privatefinalConverters转换器=newConverters();publicvoidaddConverter(GenericConverterconverter){这个。converters.add(转换器);}}Formatter最终适配GenericConverter(类型转换接口)2.基于注解的格式化字段格式化可以通过字段类型或者注解进行配置。要将注释绑定到格式化程序,请实施AnnotationFormatterFactory。publicinterfaceAnnotationFormatterFactory{Set>getFieldTypes();PrintergetPrinter(Aannotation,ClassfieldType);ParsergetParser(Aannotation,ClassfieldType);}类及方法说明:将A参数化为字段注解类型,并希望将字段关联格式化逻辑,如org.springframework.format.annotation.日期时间格式。getFieldTypes()返回可以注释的字段类型。getPrinter()返回一个Printer来打印注释字段的值。getParser()返回一个Parser来解析带注释的字段的clientValue。自定义注解解析器。公共类StringToDateFormatter实现AnnotationFormatterFactory{@OverridepublicSet>getFieldTypes(){returnnewHashSet>(Arrays.asList(Date.class));}@OverridepublicPrintergetPrinter(DateFormatterannotation,ClassfieldType){returngetFormatter(annotation,fieldType);}@OverridepublicParsergetParser(DateFormatterannotation,ClassfieldType){returngetFormatter(annotation,fieldType);}privateStringFormattergetFormatter(DateFormatterannotation,ClassfieldType){Stringpattern=annotation.value();返回新的StringFormatter(模式);}classStringFormatterimplementsFormatter{私有字符串模式;publicStringFormatter(Stringpattern){this.pattern=pattern;}@OverridepublicStringprint(Datedate,Localelocale){returnDateTimeFormatter.ofPattern(pattern,locale).format(date.toInstant());}@OverridepublicDateparse(Stringtext,Localelocale)throwsParseException{DateTimeFormatterformatter=DateTimeFormatter.ofPattern(pattern,locale);返回Date.from(LocalDate.parse(text,formatter).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());}}}注册及使用:publicclassMain{@DateFormatter("yyyy年MM月dd日")privateDatedate;publicstaticvoidmain(String[]args)throwsException{FormattingConversionServicefcs=newFormattingConversionService();fcs.addFormatterForFieldAnnotation(newStringToDateFormatter());主要主要=新主要();字段field=main.getClass().getDeclaredField("date");TypeDescriptortargetType=newTypeDescriptor(field);Objectresult=fcs.convert("2022年01月21日",targetType);System.out.println(结果);field.setAccessible(true);field.set(主要,结果);System.out.println(main.date);}}3,FormatterRegistryFormatterRegistry用于注册格式化器和转换器SPIFormattingConversionService是FormatterRegistry的一个实现,适用于大多数环境。该变体可以通过编程方式或声明方式配置为Springbean,例如使用FormattingConversionServiceFactoryBean。因为此实现还实现了ConversionService,所以您可以直接配置它以与Spring的DataBinder和SpringExpressionLanguage(SpEL)一起使用。publicinterfaceFormatterRegistryextendsConverterRegistry{voidaddPrinter(Printerprinter);voidaddParser(解析器解析器);voidaddFormatter(Formatter格式化程序);voidaddFormatterForFieldType(ClassfieldType,Formatterformatter);voidaddFormatterForFieldType(ClassfieldType,Printerprinter,Parserparser);voidaddFormatterForFieldAnnotation(AnnotationFormatterForFieldAnnotation(AnnotationFormatterFactoryannotationFormatterFactory);}4、SpringMVC中配置类型转换@Configuration@EnableWebMvcpublicclassWebConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddFormatters(FormatterRegistryregistry){//...}}SpringBoot中有如下的默认类型转换器。publicclassWebMvcAutoConfiguration{publicstaticclassEnableWebMvcConfigurationextendsDelegatingWebMvcConfigurationimplementsResourceLoaderAware{@Bean@OverridepublicFormattingConversionServicemvcConversionService(){格式格式=this.mvcProperties.getFormat();WebConversionServiceconversionService=newWebConversionService(newDateTimeFormatters().dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));添加格式化程序(转换服务);返回转换服务;}}}