亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring中自定義數(shù)據(jù)類型轉(zhuǎn)換的方法詳解

 更新時間:2022年06月20日 09:23:09   作者:Spring全家桶實(shí)戰(zhàn)案例  
Spring3引入了一個core.onvert包,提供一個通用類型轉(zhuǎn)換系統(tǒng)。在Spring容器中,可以使用這個系統(tǒng)作為PropertyEditor實(shí)現(xiàn)的替代,將外部化的bean屬性值字符串轉(zhuǎn)換為所需的屬性類型。本文將詳解這一系統(tǒng)的使用方法,需要的可以參考一下

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

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

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

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

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

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

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

ConfigurableConversionService接口。

public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {
}

Spring提供了GenericConversionService 實(shí)現(xiàn)類;該類適合在大多數(shù)環(huán)境中使用的基本 ConversionService實(shí)現(xiàn)。通過

ConfigurableConversionService接口間接實(shí)現(xiàn)ConverterRegistry作為注冊API。該類沒有提供默認(rèn)的類型轉(zhuǎn)換功能,需要我們自己添加轉(zhuǎn)換接口。

示例:

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

以上代碼運(yùn)行將報(bào)錯:

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的支持,可對對象進(jìn)行打印展示及將源數(shù)據(jù)解析成目標(biāo)對象,示例:

FormattingConversionService fcs = new FormattingConversionService() ;
fcs.addParser(new Parser<Teacher>() {
  @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<Teacher>() {
  @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ù)默認(rèn)沒有任何的類型轉(zhuǎn)換能力,都需要我們自定義添加,在Spring中還提供了DefaultConversionService 和 WebConversionService。

通過名稱知道WebConversionService 針對Web項(xiàng)目,但是你也是可以在非Web項(xiàng)目中使用。這里我就介紹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)換都能成功,為什么呢?因?yàn)镈efaultConversionService 內(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)換功能,詳細(xì)查看源碼
    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)境下默認(rè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<ConversionService>, 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<? extends ConversionService> 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)換方式。

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

實(shí)現(xiàn)Converter接口

Converter接口。

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

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

DefaultConversionService cs = new DefaultConversionService();
// 自定義類型轉(zhuǎn)換器,當(dāng)有了ConversionService完全可以替代PropertyEditor
cs.addConverter(new Converter<String, Users>() {
  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) ;

實(shí)現(xiàn)ConverterFactory接口

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

ConverterFactory接口。

public interface ConverterFactory<S, R> {
  <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

自定義工廠類。

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

實(shí)現(xiàn)GenericConverter接口

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

GenericConverter接口。

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

自定義GenericConverter。

public class CustomGenericConverter implements GenericConverter {
  @Override
  public Set<ConvertiblePair> getConvertibleTypes() {
    // 這里我們可以定義多組的類型轉(zhuǎn)換關(guān)系
    ConvertiblePair teacherPair = new ConvertiblePair(String.class, Teacher.class) ;
    ConvertiblePair studentPair = new ConvertiblePair(String.class, Student.class) ;
    Set<ConvertiblePair> 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 ;
  }
}

以上就是Spring中自定義數(shù)據(jù)類型轉(zhuǎn)換的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring數(shù)據(jù)類型轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java使用正則表達(dá)式截取重復(fù)出現(xiàn)的XML字符串功能示例

    Java使用正則表達(dá)式截取重復(fù)出現(xiàn)的XML字符串功能示例

    這篇文章主要介紹了Java使用正則表達(dá)式截取重復(fù)出現(xiàn)的XML字符串功能,涉及java針對xml字符串及指定格式字符串的正則匹配相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • 詳解Spring Security認(rèn)證流程

    詳解Spring Security認(rèn)證流程

    這篇文章主要介紹了Spring Security認(rèn)證流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Spring從@Aspect到Advisor使用演示實(shí)例

    Spring從@Aspect到Advisor使用演示實(shí)例

    這篇文章主要介紹了Spring從@Aspect到Advisor使用演示實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Java之實(shí)現(xiàn)十進(jìn)制與十六進(jìn)制轉(zhuǎn)換案例講解

    Java之實(shí)現(xiàn)十進(jìn)制與十六進(jìn)制轉(zhuǎn)換案例講解

    這篇文章主要介紹了Java之實(shí)現(xiàn)十進(jìn)制與十六進(jìn)制轉(zhuǎn)換案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 詳細(xì)分析Java Lambda表達(dá)式

    詳細(xì)分析Java Lambda表達(dá)式

    這篇文章主要介紹了Java Lambda表達(dá)式的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • springboot2.3 整合mybatis-plus 高級功能及用法詳解

    springboot2.3 整合mybatis-plus 高級功能及用法詳解

    這篇文章主要介紹了springboot2.3 整合mybatis-plus 高級功能,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • java 中RandomAccess接口源碼分析

    java 中RandomAccess接口源碼分析

    這篇文章主要介紹了java 中RandomAccess接口源碼分析的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Java抽象類和抽象方法定義與用法實(shí)例詳解

    Java抽象類和抽象方法定義與用法實(shí)例詳解

    這篇文章主要介紹了Java抽象類和抽象方法定義與用法,結(jié)合實(shí)例形式詳細(xì)分析了Java抽象類和抽象方法相關(guān)原理、定義、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-11-11
  • 簡單分析Java的求值策略原理

    簡單分析Java的求值策略原理

    在本篇文章里小編給大家整理的是一篇關(guān)于簡單分析Java的求值策略原理內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2021-06-06
  • springboot啟動時如何獲取端口和項(xiàng)目名

    springboot啟動時如何獲取端口和項(xiàng)目名

    這篇文章主要介紹了springboot啟動時如何獲取端口和項(xiàng)目名,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評論