一、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接口靈活和復雜的地方。