日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Spring中自定義數(shù)據(jù)類型轉(zhuǎn)換詳解

環(huán)境:Spring5.3.12.RELEASE。

創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),撫松企業(yè)網(wǎng)站建設(shè),撫松品牌網(wǎng)站建設(shè),網(wǎng)站定制,撫松網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,撫松網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

Spring 3引入了一個core.onvert包,提供一個通用類型轉(zhuǎn)換系統(tǒng)。系統(tǒng)定義了一個SPI來實現(xiàn)類型轉(zhuǎn)換邏輯,以及一個API來在運行時執(zhí)行類型轉(zhuǎn)換。在Spring容器中,可以使用這個系統(tǒng)作為PropertyEditor實現(xiàn)的替代,將外部化的bean屬性值字符串轉(zhuǎn)換為所需的屬性類型。還可以在應(yīng)用程序中需要類型轉(zhuǎn)換的任何地方使用公共API。

一、類型轉(zhuǎn)換服務(wù)

ConversionService類型轉(zhuǎn)換服務(wù)的接口。

public interface ConversionService {
// 判斷是否能進行轉(zhuǎn)換
boolean canConvert(Class sourceType, Class targetType);
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
// 進行類型轉(zhuǎn)換
T convert(Object source, Class targetType);
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

在大多數(shù)情況下我們應(yīng)該實現(xiàn)。

ConfigurableConversionService可配置的類型轉(zhuǎn)換服務(wù)接口。該接口整合ConversionService的所有操作和ConverterRegistry接口的相關(guān)操作,可對具體的轉(zhuǎn)換進行增刪。在應(yīng)用程序上下文引導(dǎo)代碼中處理ConfigurableEnvironment實例時,后者特別有用。

ConfigurableConversionService接口。

public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {
}

Spring提供了GenericConversionService 實現(xiàn)類;該類適合在大多數(shù)環(huán)境中使用的基本 ConversionService實現(xiàn)。通過
ConfigurableConversionService接口間接實現(xiàn)ConverterRegistry作為注冊API。該類沒有提供默認的類型轉(zhuǎn)換功能,需要我們自己添加轉(zhuǎn)換接口。

示例:

GenericConversionService gcs = new GenericConversionService() ;
Long result = gcs.convert("10", Long.class) ;
System.out.println(result) ;

以上代碼運行將報錯:

Exception in thread "main" org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Long]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at com.pack.main.conversion.GenericConversionServiceMain.main(GenericConversionServiceMain.java:9)

沒有轉(zhuǎn)換接口發(fā)現(xiàn)錯誤。

FormattingConversionService 類是GenericConversionService 子類對象,主要作用就是增加了格式化功能(還是類型轉(zhuǎn)換的一種表現(xiàn)),該類提供了 Printer和Parser的支持,可對對象進行打印展示及將源數(shù)據(jù)解析成目標對象,示例:

FormattingConversionService fcs = new FormattingConversionService() ;
fcs.addParser(new Parser() {
@Override
public Teacher parse(String text, Locale locale) throws ParseException {
String[] t = text.split("\\|") ;
return new Teacher(t[0], Integer.valueOf(t[1])) ;
}
});
System.out.println(fcs.convert("張晶晶|26", Teacher.class)) ;

這里的addParser方法最后還是將Parser轉(zhuǎn)換為GenericConverter。

將對象轉(zhuǎn)換為可讀的信息,示例:

FormattingConversionService fcs = new FormattingConversionService() ;
fcs.addPrinter(new Printer() {
@Override
public String print(Teacher object, Locale locale) {
return "【 name = " + object.getName() + ", age = " + object.getAge() + "】" ;
}
});
System.out.println(fcs.convert(new Teacher("張晶晶", 26), String.class)) ;

以上介紹的類型轉(zhuǎn)換服務(wù)默認沒有任何的類型轉(zhuǎn)換能力,都需要我們自定義添加,在Spring中還提供了DefaultConversionService 和 WebConversionService。

通過名稱知道WebConversionService 針對Web項目,但是你也是可以在非Web項目中使用。這里我就介紹DefaultConversionService 。先看示例:

DefaultConversionService dcs = new DefaultConversionService() ;
Long result = dcs.convert("10", Long.class) ;
Date date = dcs.convert("2022-07-01", Date.class) ;
System.out.println(result) ;
System.out.println(date) ;

上面兩個類型的轉(zhuǎn)換都能成功,為什么呢?因為DefaultConversionService 內(nèi)部已經(jīng)幫我們注冊了很多的類型轉(zhuǎn)換,源碼:

public class DefaultConversionService extends GenericConversionService {
public DefaultConversionService() {
addDefaultConverters(this);
}
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
addScalarConverters(converterRegistry);
// 該方法中還注冊了很多集合,流數(shù)據(jù)類型的轉(zhuǎn)換功能,詳細查看源碼
addCollectionConverters(converterRegistry);
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToTimeZoneConverter());
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}
}

通常我們一般都是使用DefaultConversionService。

在Web環(huán)境下默認使用的WebConversionService ,這里以SpringBoot為例,源碼如下:

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;
}
}
}

WebConversionService的繼承關(guān)系

public class WebConversionService extends DefaultFormattingConversionService {}
public class DefaultFormattingConversionService extends FormattingConversionService {}
public class FormattingConversionService extends GenericConversionService
implements FormatterRegistry, EmbeddedValueResolverAware {
}

Spring還提供了一個ConversionServiceFactoryBean來注冊我們自定義的類型轉(zhuǎn)換。

public class ConversionServiceFactoryBean implements FactoryBean, InitializingBean {
private Set converters;
private GenericConversionService conversionService;
public void setConverters(Set converters) {
this.converters = converters;
}
@Override
public void afterPropertiesSet() {
this.conversionService = createConversionService();
ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
}
protected GenericConversionService createConversionService() {
return new DefaultConversionService();
}
@Override
public ConversionService getObject() {
return this.conversionService;
}
@Override
public Class getObjectType() {
return GenericConversionService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

我們可以定個該Bean,然后注入converters屬性值。

@Bean
public ConversionServiceFactoryBean conversionService() {
ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean() ;
// 自定義的類型轉(zhuǎn)換
factory.setConverters(...) ;
return factory ;
}

Spring的類型轉(zhuǎn)換服務(wù)是不是挺簡單?接下來介紹Spring提供的各種自定義類型轉(zhuǎn)換方式。

接下來我們都是以示例為主。

實現(xiàn)Converter接口

Converter接口。

@FunctionalInterface
public interface Converter {
T convert(S source);
}

自定義Converter接口,我們使用匿名內(nèi)部類實現(xiàn)。

DefaultConversionService cs = new DefaultConversionService();
// 自定義類型轉(zhuǎn)換器,當(dāng)有了ConversionService完全可以替代PropertyEditor
cs.addConverter(new Converter() {
public Users convert(String source) {
String[] temp = source.split("\\|") ;
return new Users(temp[0], Integer.parseInt(temp[1])) ;
}
}) ;
Users users = cs.convert("張三|100", Users.class) ;
System.out.println(users) ;

實現(xiàn)ConverterFactory接口

當(dāng)你需要集中整個類層次結(jié)構(gòu)的轉(zhuǎn)換邏輯時(例如,當(dāng)從String轉(zhuǎn)換到Enum對象時),你可以實現(xiàn)ConverterFactory。也就是有繼承關(guān)系的類型轉(zhuǎn)換。

ConverterFactory接口。

public interface ConverterFactory {
Converter getConverter(Class targetType);
}

自定義工廠類。

public class EnvObjectConvert implements ConverterFactory {
@Override
public Converter getConverter(Class targetType) {
return new EnvConvert();
}
private class EnvConvert implements Converter {
@Override
public T convert(String source) {
String[] temp = source.split("\\|") ;
return (T) new EnvObject(temp[0], Integer.valueOf(temp[1])) ;
}
}
}

實現(xiàn)GenericConverter接口

當(dāng)你需要復(fù)雜的Converter實現(xiàn)時,請考慮使用GenericConverter接口。與Converter相比,GenericConverter具有更靈活但強類型較少的簽名,因此它支持在多個源類型和目標類型之間進行轉(zhuǎn)換。此外,GenericConverter提供了可用的源和目標字段上下文,你可以在實現(xiàn)轉(zhuǎn)換邏輯時使用它們。這樣的上下文允許通過字段注釋或在字段簽名上聲明的泛型信息驅(qū)動類型轉(zhuǎn)換。下面的清單顯示了GenericConverter的接口定義:

GenericConverter接口。

public interface GenericConverter {
Set getConvertibleTypes();
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

自定義GenericConverter。

public class CustomGenericConverter implements GenericConverter {
@Override
public Set getConvertibleTypes() {
// 這里我們可以定義多組的類型轉(zhuǎn)換關(guān)系
ConvertiblePair teacherPair = new ConvertiblePair(String.class, Teacher.class) ;
ConvertiblePair studentPair = new ConvertiblePair(String.class, Student.class) ;
Set pairs = new HashSet<>() ;
pairs.add(teacherPair) ;
pairs.add(studentPair) ;
return pairs ;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
// 下面分別看到不同的類型做不同的處理
String str = null ;
if (sourceType.getObjectType() == String.class) {
str = (String) source ;
}
if (targetType.getObjectType() == Teacher.class) {
String[] t = str.split("\\|") ;
return new Teacher(t[0], Integer.valueOf(t[1])) ;
}
if (targetType.getObjectType() == Student.class) {
String[] t = str.split("\\|") ;
return new Student(t[0], t[1]) ;
}
return null ;
}
}

當(dāng)前名稱:Spring中自定義數(shù)據(jù)類型轉(zhuǎn)換詳解
瀏覽路徑:http://m.5511xx.com/article/codhgop.html