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