这是一个基于Easyexcel通过注解的方式,实现在导入导出的时候,按照指定的字段和枚举类,进行字典值映射转换的工具。
不通过枚举类、而是直接在注解中写替换枚举的,请看另外一篇文章:EasyExcel 自定义转换器、自定义导出字典映射替换、满足条件内容增加样式,完整代码+详细注释说明
以下正文:
1.定义枚举类
/**
* @Description:
* @author: CloverAn
* @email: 285135288@qq.com
* @created: 2024/08/14 15:01
*/
public enum SexEunm implements DoGetEnum<String> {
/*需要修改的内容 - BEGIN*/
MAN("0-1", "男"),
WOMAN("1-2", "女");
/*需要修改的内容 - END*/
final String enumKey;
final String enumDesc;
SexEunm(String enumKey, String enumDesc) {
this.enumKey = enumKey;
this.enumDesc = enumDesc;
}
/**
* 根据key获取value值
*
* @param key
* @return
*/
public SexEunm getEnumByKey(String key) {
for (SexEunm sexEunm : SexEunm.values()) {
if (sexEunm.enumKey.equals(key)) {
return sexEunm;
}
}
return null;
}
/**
* 根据value获取枚举key值
*
* @param value
* @return
*/
public SexEunm getEnumByValue(String value) {
for (SexEunm sexEunm : SexEunm.values()) {
if (sexEunm.enumDesc.equals(value)) {
return sexEunm;
}
}
return null;
}
@Override
public String getValueByKey(String key) {
SexEunm sexEunm = getEnumByKey(key);
return sexEunm == null ? null : sexEunm.enumDesc;
}
@Override
public String getKeyByValue(String value) {
SexEunm sexEunm = getEnumByValue(enumDesc);
return sexEunm == null ? null : sexEunm.enumKey;
}
}
注意:
1.定义了通过key获取value 和 通过value获取key 的两个方法。这两个方法必须在自己写的类里面必须要有。此外,对于大多数情况来说,只需要修改内容里面的枚举值即可,代码里面做了标识,整体不需要改动。
2.这里继承了一个DoGetEnum类,并实现了其中的两个方法。原因是太菜,没找到通过反射执行获取对应内置函数的办法,因此通过外部接口的方式,获取对应函数方法,并执行获取数据。接口代码如下:
/**
* @Description: converter中反射获取的查询数据的方法,
* 对反射应用不熟,没有想到办法直接写在枚举类中,所以写一个接口,让枚举类实现。
* @Creator: CloverAn
* @Date: 2024/8/14 17:22
*/
public interface DoGetEnum<T> {
/**
* 根据字典key值获取对应value值,主要用于导出时字典映射转换
*
* @param key 字典值
* @return 描述
*/
String getValueByKey(T key);
/**
* 根据value获取对应字典key值,主要用于导入时字典映射转换
*
* @param value 描述
* @return 字典值
*/
T getKeyByValue(String value);
}
2.定义自定义注解
import java.lang.annotation.*;
/**
* @Description: 字典映射转换自定义注解
* @Creator: CloverAn
* @Date: 2024/8/14 17:22
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelEnumValue {
Class<? extends Enum<?>> value();
}
这里的枚举类,属性接收的是一个枚举类的对象。
3.重写EasyExcel转换器接口,对excel读和写方法都进行自定义
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Description: 自定义converter
* @Creator: CloverAn
* @Date: 2024/8/14 17:22
*/
public class ExcelEnumValueConverter implements Converter<Object> {
@Override
public Class<?> supportJavaTypeKey() {
return Object.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public WriteCellData<?> convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
ExcelEnumValue enumValue = contentProperty.getField().getAnnotation(ExcelEnumValue.class);
Class<?> enumClass = enumValue.value();
Object enumConstant = enumClass.getEnumConstants()[0];
Method method = null;
Object invoke = null;
try {
//获取枚举类中的方法并执行,以期望获取到对应的value值数据
method = enumClass.getDeclaredMethod("getValueByKey", Object.class);
invoke = method.invoke(enumConstant, value);
} catch (NoSuchMethodException e) {
//抛出getValueByKey方法未找到异常
} catch (InvocationTargetException | IllegalAccessException e) {
//抛出getValueByKey方法调用失败异常
}
//Method method = null;
//try {
// method = enumClass.getDeclaredMethod("getValueByKey", Object.class);
//} catch (NoSuchMethodException e) {
// //抛出getValueByKey方法未找到异常
//}
//Object invoke = null;
//try {
// invoke = method.invoke(enumConstant, value);
//} catch (Exception e) {
// //抛出getValueByKey方法调用失败异常
//}
//注意,当枚举类中没有对应的key时,或者对应key的value是null时,invoke会返回null,此时会出现空指针。
if (invoke == null) {
invoke = "未找到指定key对应的value值";
}
return new WriteCellData<>(invoke.toString());
}
@Override
public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String stringValue = cellData.getStringValue();
ExcelEnumValue enumValue = contentProperty.getField().getAnnotation(ExcelEnumValue.class);
Class<?> enumClass = enumValue.value();
Object enumConstant = enumClass.getEnumConstants()[0];
Method method = null;
Object invoke = null;
try {
//获取枚举类中的方法并执行,以期望获取到对应的key值数据
method = enumClass.getDeclaredMethod("getKeyByValue", String.class);
invoke = method.invoke(enumConstant, stringValue);
} catch (NoSuchMethodException e) {
try {
//获取枚举类中的方法并执行,以期望获取到对应的key值数据
method = enumClass.getDeclaredMethod("getKeyByValue", Object.class);
invoke = method.invoke(enumConstant, stringValue);
} catch (NoSuchMethodException ex) {
//抛出getKeyByValue方法未找到异常
}
}
//Method method = null;
//try {
// method = enumClass.getDeclaredMethod("getKeyByValue", String.class);
//} catch (NoSuchMethodException e) {
// try {
// method = enumClass.getDeclaredMethod("getKeyByValue", Object.class);
// } catch (NoSuchMethodException ex) {
// //抛出getKeyByValue方法未找到异常
// }
//}
//Object invoke = null;
//try {
// invoke = method.invoke(enumConstant, stringValue);
//} catch (Exception e) {
// //抛出getKeyByValue方法调用失败异常
//}
//注意,当枚举类中没有对应的value时,或者对应value的key是null时,invoke会返回null,此时会出现空指针。
if (invoke == null) {
invoke = "未找到指定value对应的key值";
}
return invoke;
}
}
1.原理就是,通过获取注解上传递进来的枚举类,通过反射获取类中的方法,并执行对应的方法获取数据。
2.这里可以做调整,并改为获取到执行内容后,进行其他的业务逻辑,比如添加样式、业务逻辑等。
4.测试实体类
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* @Description:
* @author: CloverAn
* @email:
* @created: 2024/08/14 14:59
*/
@Data
public class SexEntity {
@ExcelProperty(value = "性别",converter = ExcelEnumValueConverter.class)
@ExcelEnumValue(SexEunm.class)
String sex;
}
这里就简单模拟了。这时候导入或者导出的时候,对应的值会根据枚举值进行替换。