说明:该文章是转载大牛的文章;尊重版权,原链接为:https://blog.youkuaiyun.com/fsadkjl/article/details/105823830
EasyExcel自定义Converter全局加载器以及加载Converter
本篇文章主要讲以下问题:
1.converter三种加载方式以及注意事项
2.EasyExcel的converter加载流程
3.自定义全局加载器converterLoader
converter三种加载方式以及注意事项
- 在需要转换的字段上的@ExcelProperty注解上添加converter属性
@ExcelProperty(value = "创建时间", index = 3, converter = LocalDateTimeConverter.class)
private LocalDateTime createTime;
-
优点:此种方式只需在每个需要转换的字段上添加converter即可
-
缺点:如果有很多类,每个类中有很多需要单独转换的字段要写很多次就尴尬了!
-
适用场景:任何场景
-
在创建ExcelWriterBuilder时候为这次操作单独加载转换器
EasyExcel.write(response.getOutputStream(), UserExport.class).registerConverter(new LocalDateTimeConverter()).sheet("test").doWrite(list);
- 优点:此种方式只要在每个导入导出的方法上都单独加载转换器,不用在每个需要转换的字段上都添加converter了,一定程度上可以减少我们的工作量
- 缺点:只在本方法中有效,其他方法无效,如果有很多不同的导入导出方法就又尴尬了!
- 适用场景:适用于LocalDateTimeConverter场景,但是如果要是SexConverter场景就不适合!因为前者是LocalDateTime与String之间的转换,后者它的本质是Integer与String互相转换,因为String字段可以代表年龄、性别、等信息,所以没法转换,不知道我描述的是否清楚?
- 自定义全局加载器CustomerDefaultConverterLoader
@Configuration
public class CustomerDefaultConverterLoader {
//存放写时用到的converter
private static final String ALL_CONVERTER = "allConverter";
//存放所有的converter
private static final String WRITE_CONVERTER = "defaultWriteConverter";
@Bean
public DefaultConverterLoader init() throws IllegalAccessException {
DefaultConverterLoader converters = new DefaultConverterLoader();
Field[] fields = converters.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.getType() == Map.class) {
Map<String, Converter> oldMap = (Map<String, Converter>) field.get(converters);
//兼容高版本(2.2.0+)通过静态代码块初始化 复用旧代码 节省空间
if (oldMap != null && !oldMap.isEmpty()) {
if (WRITE_CONVERTER.equalsIgnoreCase(field.getName())) {
putWriteConverter(oldMap, new LocalDateTimeConverter());
} else if (ALL_CONVERTER.equalsIgnoreCase(field.getName())) {
putAllConverter(oldMap, new LocalDateTimeConverter());
}
field.set(converters, oldMap);
} else {
setConverter(converters, field);
}
}
}
return converters;
}
private void setConverter(DefaultConverterLoader converters, Field field) throws IllegalAccessException {
if (WRITE_CONVERTER.equalsIgnoreCase(field.getName())) {
Map<String, Converter> map = new HashMap<>(32);
//我的LocalDateTimeConverter
putWriteConverter(map, new LocalDateTimeConverter());
//以下jar包自带的Converter
putWriteConverter(map, new BigDecimalNumberConverter());
putWriteConverter(map, new BooleanBooleanConverter());
putWriteConverter(map, new ByteNumberConverter());
putWriteConverter(map, new DateStringConverter());
putWriteConverter(map, new DoubleNumberConverter());
putWriteConverter(map, new FloatNumberConverter());
putWriteConverter(map, new IntegerNumberConverter());
putWriteConverter(map, new LongNumberConverter());
putWriteConverter(map, new ShortNumberConverter());
putWriteConverter(map, new StringStringConverter());
putWriteConverter(map, new FileImageConverter());
putWriteConverter(map, new InputStreamImageConverter());
putWriteConverter(map, new ByteArrayImageConverter());
putWriteConverter(map, new BoxingByteArrayImageConverter());
putWriteConverter(map, new UrlImageConverter());
field.set(converters, map);
} else if (ALL_CONVERTER.equalsIgnoreCase(field.getName())) {
Map<String, Converter> map = new HashMap<>(64);
//我的LocalDateTimeConverter
putAllConverter(map, new LocalDateTimeConverter());
//以下jar包自带的Converter
putAllConverter(map, new BigDecimalBooleanConverter());
putAllConverter(map, new BigDecimalNumberConverter());
putAllConverter(map, new BigDecimalStringConverter());
putAllConverter(map, new BooleanBooleanConverter());
putAllConverter(map, new BooleanNumberConverter());
putAllConverter(map, new BooleanStringConverter());
putAllConverter(map, new ByteBooleanConverter());
putAllConverter(map, new ByteNumberConverter());
putAllConverter(map, new ByteStringConverter());
putAllConverter(map, new DateNumberConverter());
putAllConverter(map, new DateStringConverter());
putAllConverter(map, new DoubleBooleanConverter());
putAllConverter(map, new DoubleNumberConverter());
putAllConverter(map, new DoubleStringConverter());
putAllConverter(map, new FloatBooleanConverter());
putAllConverter(map, new FloatNumberConverter());
putAllConverter(map, new FloatStringConverter());
putAllConverter(map, new IntegerBooleanConverter());
putAllConverter(map, new IntegerNumberConverter());
putAllConverter(map, new IntegerStringConverter());
putAllConverter(map, new LongBooleanConverter());
putAllConverter(map, new LongNumberConverter());
putAllConverter(map, new LongStringConverter());
putAllConverter(map, new ShortBooleanConverter());
putAllConverter(map, new ShortNumberConverter());
putAllConverter(map, new ShortStringConverter());
putAllConverter(map, new StringBooleanConverter());
putAllConverter(map, new StringNumberConverter());
putAllConverter(map, new StringStringConverter());
putAllConverter(map, new StringErrorConverter());
field.set(converters, map);
}
}
private void putWriteConverter(Map<String, Converter> map, Converter converter) {
map.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter);
}
private void putAllConverter(Map<String, Converter> map, Converter converter) {
map.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), converter);
}
}
- 优点:此种方式可以全局配置Converter,一劳永逸!配置完之后不用再单独修改字段或者修改方法,可以理解为EasyExcel从现在支持LocalDateTime啦!
- 缺点:只能添加特殊的Converter
- 适用场景:与第二种场景一样!切记SexConverter不可放到全局加载器中,不信你试试。。。试过之后你就理解我为什么写这么多文字去介绍他们的适用场景了