新聞中心
環(huán)境:Spring5.3.12.RELEASE。

Spring提供的一個(gè)core.convert包是一個(gè)通用類型轉(zhuǎn)換系統(tǒng)。它提供了統(tǒng)一的ConversionService API和強(qiáng)類型的Converter SPI,用于實(shí)現(xiàn)從一種類型到另一種類型的轉(zhuǎn)換邏輯。Spring容器使用這個(gè)系統(tǒng)綁定bean屬性值。此外,Spring Expression Language (SpEL)和DataBinder都使用這個(gè)系統(tǒng)來綁定字段值。例如,當(dāng)SpEL需要將Short強(qiáng)制轉(zhuǎn)換為Long來完成表達(dá)式時(shí)。setValue(對象bean,對象值)嘗試,核心。轉(zhuǎn)換系統(tǒng)執(zhí)行強(qiáng)制轉(zhuǎn)換。
現(xiàn)在考慮典型客戶端環(huán)境(例如web或桌面應(yīng)用程序)的類型轉(zhuǎn)換需求。在這種環(huán)境中,通常從String轉(zhuǎn)換為支持客戶端回發(fā)過程,并返回String以支持視圖呈現(xiàn)過程。此外,你經(jīng)常需要本地化String值。更一般的core.convert Converter SPI不能直接解決這些格式要求。為了直接解決這些問題,Spring 3引入了一個(gè)方便的Formatter SPI,它為客戶端環(huán)境提供了PropertyEditor實(shí)現(xiàn)的一個(gè)簡單而健壯的替代方案。
通常,當(dāng)你需要實(shí)現(xiàn)通用類型轉(zhuǎn)換邏輯時(shí),你可以使用Converter SPI,例如,用于java.util.Date和Long之間的轉(zhuǎn)換。當(dāng)你在客戶端環(huán)境(例如web應(yīng)用程序)中工作并需要解析和打印本地化的字段值時(shí),你可以使用Formatter SPI。ConversionService為這兩個(gè)spi提供了統(tǒng)一的類型轉(zhuǎn)換API。
1、Formatter SPI
實(shí)現(xiàn)字段格式化邏輯的Formatter SPI是簡單且強(qiáng)類型的。下面的清單顯示了Formatter接口定義:
package org.springframework.format;
public interface Formatterextends Printer , Parser {
}
Formatter繼承自Printer和Parser接口。
@FunctionalInterface
public interface Printer{
String print(T object, Locale locale);
}
@FunctionalInterface
public interface Parser{
T parse(String text, Locale locale) throws ParseException;
}
默認(rèn)情況下Spring容器提供了幾個(gè)Formatter實(shí)現(xiàn)。數(shù)字包提供了NumberStyleFormatter、CurrencyStyleFormatter和PercentStyleFormatter來格式化使用java.text.NumberFormat的number對象。datetime包提供了一個(gè)DateFormatter來用java.text.DateFormat格式化 java.util.Date對象。
自定義Formatter。
public class StringToNumberFormatter implements Formatter{
@Override
public String print(Number object, Locale locale) {
return "結(jié)果是:" + object.toString();
}
@Override
public Number parse(String text, Locale locale) throws ParseException {
return NumberFormat.getInstance().parse(text);
}
}
如何使用?我們可以通過FormattingConversionService 轉(zhuǎn)換服務(wù)進(jìn)行添加自定義的格式化類。
FormattingConversionService fcs = new FormattingConversionService();
// 默認(rèn)如果不添加自定義的格式化類,那么程序運(yùn)行將會報(bào)錯
fcs.addFormatterForFieldType(Number.class, new StringToNumberFormatter());
Number number = fcs.convert("100.5", Number.class);
System.out.println(number);
查看源碼:
public class FormattingConversionService extends GenericConversionService implements FormatterRegistry, EmbeddedValueResolverAware {
public void addFormatterForFieldType(Class> fieldType, Formatter> formatter) {
addConverter(new PrinterConverter(fieldType, formatter, this));
addConverter(new ParserConverter(fieldType, formatter, this));
}
private static class PrinterConverter implements GenericConverter {}
private static class ParserConverter implements GenericConverter {}
}
public class GenericConversionService implements ConfigurableConversionService {
private final Converters converters = new Converters();
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
}
}Formatter最后還是被適配成GenericConverter(類型轉(zhuǎn)換接口)。
2、基于注解的格式化
字段格式化可以通過字段類型或注釋進(jìn)行配置。要將注釋綁定到Formatter,請實(shí)現(xiàn)AnnotationFormatterFactory。
public interface AnnotationFormatterFactory {
Set> getFieldTypes();
Printer> getPrinter(A annotation, Class> fieldType);
Parser> getParser(A annotation, Class> fieldType);
}
類及其方法說明:
參數(shù)化A為字段注解類型,你希望將該字段與格式化邏輯關(guān)聯(lián),例如org.springframework.format.annotation.DateTimeFormat。
- getFieldTypes()返回可以使用注釋的字段類型。
- getPrinter()返回一個(gè)Printer來打印帶注釋的字段的值。
- getParser()返回一個(gè)Parser來解析帶注釋字段的clientValue。
自定義注解解析器。
public class StringToDateFormatter implements AnnotationFormatterFactory{
@Override
public Set> getFieldTypes() {
return new HashSet>(Arrays.asList(Date.class));
}
@Override
public Printer> getPrinter(DateFormatter annotation, Class> fieldType) {
return getFormatter(annotation, fieldType);
}
@Override
public Parser> getParser(DateFormatter annotation, Class> fieldType) {
return getFormatter(annotation, fieldType);
}
private StringFormatter getFormatter(DateFormatter annotation, Class> fieldType) {
String pattern = annotation.value();
return new StringFormatter(pattern);
}
class StringFormatter implements Formatter{
private String pattern;
public StringFormatter(String pattern) {
this.pattern = pattern;
}
@Override
public String print(Date date, Locale locale) {
return DateTimeFormatter.ofPattern(pattern, locale).format(date.toInstant());
}
@Override
public Date parse(String text, Locale locale) throws ParseException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, locale);
return Date.from(LocalDate.parse(text, formatter).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
}
}
注冊及使用:
public class Main {
@DateFormatter("yyyy年MM月dd日")
private Date date;
public static void main(String[] args) throws Exception {
FormattingConversionService fcs = new FormattingConversionService();
fcs.addFormatterForFieldAnnotation(new StringToDateFormatter());
Main main = new Main();
Field field = main.getClass().getDeclaredField("date");
TypeDescriptor targetType = new TypeDescriptor(field);
Object result = fcs.convert("2022年01月21日", targetType);
System.out.println(result);
field.setAccessible(true);
field.set(main, result);
System.out.println(main.date);
}
}
3、FormatterRegistry
FormatterRegistry是用于注冊格式化程序和轉(zhuǎn)換器的SPI。FormattingConversionService是FormatterRegistry的一個(gè)實(shí)現(xiàn),適用于大多數(shù)環(huán)境。可以通過編程或聲明的方式將該變體配置為Spring bean,例如使用FormattingConversionServiceFactoryBean。因?yàn)檫@個(gè)實(shí)現(xiàn)還實(shí)現(xiàn)了ConversionService,所以您可以直接配置它,以便與Spring的DataBinder和Spring表達(dá)式語言(SpEL)一起使用。
public interface FormatterRegistry extends ConverterRegistry {
void addPrinter(Printer> printer);
void addParser(Parser> parser);
void addFormatter(Formatter> formatter);
void addFormatterForFieldType(Class> fieldType, Formatter> formatter);
void addFormatterForFieldType(Class> fieldType, Printer> printer, Parser> parser);
void addFormatterForFieldAnnotation(AnnotationFormatterFactory extends Annotation> annotationFormatterFactory);
}
4、SpringMVC中配置類型轉(zhuǎn)換
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
SpringBoot中有如下的默認(rèn)類型轉(zhuǎn)換器。
public class WebMvcAutoConfiguration {
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
@Bean
@Override
public FormattingConversionService mvcConversionService() {
Format format = this.mvcProperties.getFormat();
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
addFormatters(conversionService);
return conversionService;
}
}
} 當(dāng)前題目:Spring中字段格式化的使用詳解
網(wǎng)頁鏈接:http://www.dlmjj.cn/article/dpeoddc.html


咨詢
建站咨詢
