来到这里的相信一般都是看过我前两篇文章了第一篇第二篇,本篇文章是对前两篇文章的补充与总结!本篇文章主要讲以下问题:

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

    查看代码

    • 优点:此种方式可以全局配置Converter,一劳永逸!配置完之后不用再单独修改字段或者修改方法,可以理解为EasyExcel从现在支持LocalDateTime啦!

    • 缺点:只能添加特殊的Converter

    • 适用场景:与第二种场景一样!切记SexConverter不可放到全局加载器中,不信你试试。。。试过之后你就理解我为什么写这么多文字去介绍他们的适用场景了

总结:如果需要LocalDateTime做转换就用第三种直接放到全局加载器中,如果需要sex做转换就用第一种!可以并存,优先级:第一种 > 第二种 > 第三种

EasyExcel的converter加载流程

  • EasyExcel的全局Converter加载器类:DefaultConverterLoader,那我们就来debug看看是怎么进行转换的
  • 大体流程就是: 读取全局加载器类 -> 写入的时候判断该字段上是否制定Converter,有则取之,没有的话 -> 根据类型去全局加载器类中查找,找不到报错,找到之后继续后面逻辑,可以根据我的图去细看

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

自定义全局加载器converterLoader

@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);
	}
}

好了EasyExcel总结到此结束,都是一些实际工作中用到的,虽然不是很深入,但是希望能够在日常工作中给大家带来帮助!

加油!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐