spring 類型轉換器Converter


一、Coverter接口,將S型轉換成T型

@FunctionalInterface
public interface Converter<S, T> {

    /**
     * Convert the source object of type {@code S} to target type {@code T}.
     * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
     * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
     * @throws IllegalArgumentException if the source cannot be converted to the desired target type
     */
    @Nullable
    T convert(S source);

}

下面寫個Demo把String轉換成Date

  (1)編寫類型轉換器DateConverter

  

public class DateConverter implements Converter<String,Date>{


    @Override
    public Date convert(String source) {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-dd-mm");
        Date date=null;
        if(StringUtils.isEmpty(source)) {
            return null;
        }
        try {
            date= sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

}

(2)把類型轉換器添加到spring中,可以在配置類中添加,也可以添加在DefaultConversionService中,Spring啟動之后自動加載該類

   

@Configuration
public class WebConfiguration {
    
    @Bean
    public GenericConversionService getGenericConversionService(@Autowired GenericConversionService conversionService) {
        conversionService.addConverter(new DateConverter());
        System.out.println("類型轉換已加入!");
        return conversionService;
        
    }
}

(3)Controller

  

@Controller
public class HelloController {
    @RequestMapping("/test")
    @ResponseBody
    public String hello( String date) {
        
        return "===="+date;
    }
}

啟動SpringBoot之后訪問測試

 

 二、ConverterFactory

     ConverterFactory就是管理繼承或者實現同一接口的converter,就是一個工廠(類似於代理,就是一個統一管理同一類型的converter)。

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

    (1)spring為我們提供了StringToNumberConverterFactory、StringToEnumConverterFactory。當瀏覽器傳參String類型的數字時,我們就可以用int、float等進行接受。枚舉也類似。以StringToNumberConverterFactory為列:

       

final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {

    @Override
    public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToNumber<>(targetType);
    }


    private static final class StringToNumber<T extends Number> implements Converter<String, T> {

        private final Class<T> targetType;

        public StringToNumber(Class<T> targetType) {
            this.targetType = targetType;
        }

        @Override
        public T convert(String source) {
            if (source.isEmpty()) {
                return null;
            }
            return NumberUtils.parseNumber(source, this.targetType);
        }
    }

}




(2)NumberUtils工具類中根據傳進來targetType類型完成轉換

  

@SuppressWarnings("unchecked")
    public static <T extends Number> T parseNumber(String text, Class<T> targetClass) {
        Assert.notNull(text, "Text must not be null");
        Assert.notNull(targetClass, "Target class must not be null");
        String trimmed = StringUtils.trimAllWhitespace(text);

        if (Byte.class == targetClass) {
            return (T) (isHexNumber(trimmed) ? Byte.decode(trimmed) : Byte.valueOf(trimmed));
        }
        else if (Short.class == targetClass) {
            return (T) (isHexNumber(trimmed) ? Short.decode(trimmed) : Short.valueOf(trimmed));
        }
        else if (Integer.class == targetClass) {
            return (T) (isHexNumber(trimmed) ? Integer.decode(trimmed) : Integer.valueOf(trimmed));
        }
        else if (Long.class == targetClass) {
            return (T) (isHexNumber(trimmed) ? Long.decode(trimmed) : Long.valueOf(trimmed));
        }
        else if (BigInteger.class == targetClass) {
            return (T) (isHexNumber(trimmed) ? decodeBigInteger(trimmed) : new BigInteger(trimmed));
        }
        else if (Float.class == targetClass) {
            return (T) Float.valueOf(trimmed);
        }
        else if (Double.class == targetClass) {
            return (T) Double.valueOf(trimmed);
        }
        else if (BigDecimal.class == targetClass || Number.class == targetClass) {
            return (T) new BigDecimal(trimmed);
        }
        else {
            throw new IllegalArgumentException(
                    "Cannot convert String [" + text + "] to target class [" + targetClass.getName() + "]");
        }
    }

 

 

  (3)當然也可以自定義ConverterFactory,一定要把其添加到spring中,負責無效,添加如下,可以在GenericConverterService\DefaultConverterService中添加

@Configuration
public class WebConfiguration {
    
    @Bean
    public GenericConversionService getDefaultConversionService(@Autowired GenericConversionService conversionService) {
        conversionService.addConverter(new TestConverterFactory());
        System.out.println("類型轉換已加入!");
        return conversionService;
        
    }
}

三、GenericConverter(多對多的轉換)

   GenericConverter接口是所有的Converter接口中最靈活也是最復雜的一個類型轉換接口。像我們之前介紹的Converter接口只支持從一個原類型轉換為一個目標類型;ConverterFactory接口只支持從一個原類型轉換為一個目標類型對應的子類型;而GenericConverter接口支持在多個不同的原類型和目標類型之間進行轉換,這也就是GenericConverter接口靈活和復雜的地方。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM