easypoi 利用现有的枚举类转换枚举名称

背景:

       使用easypoi 作为导入导出框架,引入的版本号是:

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.0.0</version>
</dependency>

使用场景:

        使用@Excel 导出实体类信息,通常我们都会通过存储枚举的编码到数据库中,而枚举值则放在代码的枚举类里。但是在我们导出的时候,则需要将枚举文字信息导出到表格里。

根据easypoi现有模式的实现:

        @Excel的属性值里使用replace,把所有的枚举值需要按照他既定的格式,再重新设置一遍。

痛点:如果枚举个数过多,需要大量重复且繁琐的配置。

针对重复冗余的动作,我们针对这个进行改造,先看效果:

        1. 通过自定义注解,设置对应的枚举类型,实现自动转换枚举信息;如果你的枚举类,key 和value 都一致,也可以省略指定key,和value;

        2. 在导出的时候显式调用工具类,即可自动注入

List<Class> classes = new ArrayList<>();
classes.add(ContractExcelVO.class);
ExcelPojoUtils.initClassExcel(classes);

实现过程:

        1.定义一个自定义注解类@ColumnExcelEnum,定义枚举的基本相关信息。

/**
 * @description:导出表格的枚举值处理方式注解,
 * 用于导出表格时,对枚举值的处理方式,如:是否是外部枚举,枚举的键属性名称,枚举的值属性名称等等
 * @author: hhq
 * @create: 2020-11-02 18:35
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
public @interface ColumnExcelEnum {
    /**
     * 对应的是否是外部枚举
     * @return
     */
    boolean externalEnum() default false;
    /**
     * 对应的枚举值名称
     * @return
     */
    String name() default "";

    /**
     * 枚举的键属性名称
     * @return
     */
    String key() default "";

    /**
     * 枚举的值属性名称
     * @return
     */
    String value() default "";
}

         2.通过传入的类名,使用反射的方式,获取属性上注入自定义注解的字段。再对属性上的@Excel 注解进行解析,动态的对@Excel 注入属性replace。

InvocationHandler handler = Proxy.getInvocationHandler(excel);

         3.下面是我自己封装的一个使用自定义注解动态替换枚举值的工具类

package com.pindao.developproject.newContract.utils;

import cn.afterturn.easypoi.excel.annotation.Excel;
import com.pindao.developproject.newContract.annotation.ColumnExcelEnum;
import com.pindao.developproject.newContract.common.Constant;
import io.swagger.models.Contact;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @description:表格导出的枚举值转化处理器
 * @author: hhq
 * @create: 2022-07-01 14:47
 **/
@Component
@Slf4j
public class ExcelPojoUtils {


    /**
     * 动态修改类信息
     *
     * @param classList
     */
    public static void initClassExcel(List<Class> classList) {
        classList.forEach(clazz -> {
            dynamicConvertEnum(clazz);
        });
    }

    /**
     * 通过类名转化枚举值
     *
     * @param clazz
     */
    public static void dynamicConvertEnum(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        //如果存在的话,且有枚举类型的话,动态修改,自动转化
        for (Field field : fields) {
            ColumnExcelEnum columnEnum = field.getAnnotation(ColumnExcelEnum.class);
            if (ObjectUtils.isEmpty(columnEnum)) {
                continue;
            }
            String enumName = columnEnum.name();
            if (!StringUtils.isEmpty(enumName)) {
                Excel excel = field.getAnnotation(Excel.class);
                InvocationHandler handler = Proxy.getInvocationHandler(excel);
                try {
                    Field anField = handler.getClass().getDeclaredField("memberValues");
                    anField.setAccessible(true);
                    Map memberMap = (Map) anField.get(handler);
                    memberMap.put("replace", convertReplace(columnEnum));
                } catch (Exception e) {
                    log.error("未找到该属性值", e);
                }
            }
        }
    }

    public static String[] convertReplace(ColumnExcelEnum columnEnum) {
        try {
            Class enumClass = null;
            String className = columnEnum.externalEnum() ? columnEnum.name() : Constant.ENUM_CURRENT_PATH + columnEnum.name();
            enumClass = Class.forName(className);
            Object[] objects = enumClass.getEnumConstants();
            Method getCodeMethod = enumClass.getMethod(columnEnum.key());
            Method getValueMethod = enumClass.getMethod(columnEnum.value());
            String[] replaces = new String[objects.length + 1];
            int i = 0;
            for (Object obj : objects) {
                replaces[i] = getValueMethod.invoke(obj) + Constant.STRING_SPLIT_UNLINE + getCodeMethod.invoke(obj);
                i++;
            }
            replaces[i] = Constant.EXCEL_NULL;
            return replaces;
        } catch (Exception e) {
            log.error("转换对应的枚举值失败", e);
        }
        return null;
    }


}

             4.工具类中使用到的常量

    /**
     * 字符串分隔符
     */
    public final static String STRING_SPLIT_UNLINE ="_";


    /**
     * 导出的枚举空值处理方式
     */
    public final static String EXCEL_NULL  ="_null";



    /**
     * 本地枚举值的路径
     */
    public static final String ENUM_CURRENT_PATH = "com.pindao.developproject.newContract.enums.";

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值