|
问题描述近期在工作过程中,业务涉及各种导入导出,且包含单选、多选问题,针对于easyExcel的一些枚举转换数据,有了一点其他想法,按照官方文档中:读Excel|EasyExcel(alibaba.com),提供了自定义转换器的实现接口,但是我在网上搜索发现都比较单一,也就是一个枚举类需要写一个单独的转换器,这样的话会增加无意义工作量,所以想到了通过自定义注解+重新easyExcel转换器实现通用的easyExcle转换器。话不多说,直接上代码:1.重写EasyExcel转换器接口,对excel读和写方法都进行自定义packagecom.example.test.excel;importcom.alibaba.excel.converters.Converter;importcom.alibaba.excel.enums.CellDataTypeEnum;importcom.alibaba.excel.metadata.GlobalConfiguration;importcom.alibaba.excel.metadata.data.ReadCellData;importcom.alibaba.excel.metadata.data.WriteCellData;importcom.alibaba.excel.metadata.property.ExcelContentProperty;importorg.springframework.util.StringUtils;importjava.lang.reflect.Field;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.stream.Collectors;/***excel导入导出针对枚举类型的转换器**@Author996*@Date2024/3/13*/publicclassEasyExcelConvertimplementsConverter{/***枚举列表*/privateMapenumMap=newHashMap();/***excel转化后的类型**@return*/@OverridepublicClasssupportJavaTypeKey(){returnObject.class;}/***excel中的数据类型,统一设置字符串**@return*/@OverridepublicCellDataTypeEnumsupportExcelTypeKey(){returnCellDataTypeEnum.STRING;}/***导入转换*@paramcellData当前单元格对象*@paramcontentProperty当前单元格属性*@paramglobalConfiguration*@return*@throwsException*/@OverridepublicObjectconvertToJavaData(ReadCellDatacellData,ExcelContentPropertycontentProperty,GlobalConfigurationglobalConfiguration)throwsException{StringcellMsg=cellData.getStringValue();Fieldfield=contentProperty.getField();EnumFiledConvertenumFiledConvert=field.getAnnotation(EnumFiledConvert.class);if(enumFiledConvert==null){returnnull;}StringenumStr=enumFiledConvert.enumMap();//解析枚举映射关系getEnumMap(enumStr,true);//是否为单选booleansingle=enumFiledConvert.single();//如果是单选,默认Java属性为integerif(single){Stringres=enumMap.get(cellMsg);returnStringUtils.hasText(res)?Integer.valueOf(res):null;}else{//多选分隔符StringspiteChar=enumFiledConvert.spiteChar();//多选枚举,默认Java属性为字符串,格式为key1,key2,key3ListstrStr=Arrays.asList(cellMsg.split(spiteChar)).stream().map(s->String.valueOf(enumMap.get(s))).collect(Collectors.toList());Stringstr=String.join(spiteChar,strStr);returnstr;}}/***导出转化*@paramvalue当前值*@paramcontentProperty当前单元格属性*@paramglobalConfiguration*@return*@throwsException*/@OverridepublicWriteCellDataconvertToExcelData(Objectvalue,ExcelContentPropertycontentProperty,GlobalConfigurationglobalConfiguration)throwsException{Fieldfield=contentProperty.getField();EnumFiledConvertenumFiledConvert=field.getAnnotation(EnumFiledConvert.class);if(enumFiledConvert==null){returnnewWriteCellData();}//解析枚举字符串StringenumStr=enumFiledConvert.enumMap();getEnumMap(enumStr,false);//是否为单选booleansingle=enumFiledConvert.single();//如果是单选,默认Java属性为integerif(single){returnnewWriteCellData(enumMap.getOrDefault(String.valueOf(value),""));}else{//多选分隔符StringspiteChar=enumFiledConvert.spiteChar();//多选枚举,默认Java属性为字符串,格式为key1,key2,key3ListstrStr=Arrays.asList(String.valueOf(value).split(spiteChar)).stream().map(s->String.valueOf(enumMap.get(s))).collect(Collectors.toList());Stringstr=String.join(spiteChar,strStr);returnnewWriteCellData(str);}}/***根据注解配置的枚举映射字符串进行解析到map中*@parammapStr*@paramreadOrWrite读excel、写excel*/privatevoidgetEnumMap(StringmapStr,booleanreadOrWrite){String[]enumS=mapStr.split(",");for(StringanEnum:enumS){String[]data=anEnum.split("-");if(readOrWrite){//读excelexcel中的数据都是value,转换成keyenumMap.put(data[1],data[0]);}else{//写excelJava中的数据都是key,转换成valueenumMap.put(data[0],data[1]);}}}}2.自定义注解,包含3个参数,分别是枚举类型的字符串,多选场景下的分隔符,单选枚举or多选枚举packagecom.example.test.excel;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/***对excel导入时,处理枚举转化*@Author996*@Date2024/3/13*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public@interfaceEnumFiledConvert{/***枚举映射mapkey-value,key-value,key-value,key-value*@return*/StringenumMap()default"";/***枚举类导入、导出在excel中的分隔符号*@return*/StringspiteChar()default",";/***单选or多选*@return*/booleansingle()defaulttrue;} 很简单吧?就是通过自定义注解,把枚举类映射关系传递到注解的参数里面。目前这个实现方式是写死在代码里面的。如果说枚举映射都存在数据库中的话,可以对方法进行改造,枚举参数传递成数据库里面的分类标识,在转换器里面去获取数据库里对应的枚举内容。上样例!先写一个用户类importcom.alibaba.excel.annotation.ExcelProperty;importcom.example.test.excel.EasyExcelConvert;importcom.example.test.excel.EnumFiledConvert;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;/***@Author996*@Date2024/3/20*/@Data@NoArgsConstructor@AllArgsConstructorpublicclassExcelDto{@ExcelProperty(value="姓名")privateStringname;@ExcelProperty(value="性别",converter=EasyExcelConvert.class)@EnumFiledConvert(enumMap="0-保密,1-男,2-女")privateIntegersex;@ExcelProperty(value="爱好",converter=EasyExcelConvert.class)@EnumFiledConvert(enumMap="1-篮球,2-足球,3-乒乓球,4-羽毛球",single=false)privateStringhobbies;}建一个对象列表,模拟数据库查询出来的数据,测试导出是否成功转换。(该方法采用excel自动生成excel,也可以是使用fill填充的方式写入指定excel模板)调用接口,查看Excel导出效果,一切正常:再测试导入,直接将这个Excel提交,查看后台接收效果:整体代码都比较简单,仅仅是提供一种思路去尽可能减少这种处理枚举转换上的无意义工作量,如果各位大佬有更好的意见,还请不吝赐教。
|
|