通过反射,实现修改easyExcel的@ExcelProperty注解的value值从而实现从配置文件读取@ExcelProperty的value

自定义注解:

package com.resuper.yhexcel.util;

import java.lang.annotation.*;


@Documented
@Inherited
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelI18N {
    String i18nkey();
}

配置文件:excel.properties

#row即表头行(起始值/最小值为1);
excel.zgnyyh.row=3
excel.zgnyyh.jysj=会计日期
excel.zgnyyh.jffse=支出金额
excel.zgnyyh.dffse=收入金额
excel.zgnyyh.jyhye=账户余额
excel.zgnyyh.fkzh=对方账号
excel.zgnyyh.fkzhm=对方户名
excel.zgnyyh.zysm=交易用途

 

excel对应的实体:

package com.resuper.yhexcel.excelData;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.resuper.yhexcel.converter.ZggsyhConverter;
import com.resuper.yhexcel.converter.ZgnyyhConverter;
import com.resuper.yhexcel.util.ExcelI18N;
import lombok.Data;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.PropertyResourceBundle;

@Data
public class Data {
    /*
    // 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
    @ExcelProperty(index = 2)
    private Double doubleData;
    // 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    */


    /**
     * 交易时间
     */
//    @ExcelProperty(value = "交易时间" , converter = ZgnyyhConverter.class)
//    @DateTimeFormat("yyyyMMdd HH:mm:ss")
//    private Date jysj;
    @ExcelI18N(i18nkey = "会计日期")
    @ExcelProperty(value = "会计日期")
    private String jysj;


    /**
     * 收入支出标志(1 收入,2 支出)
     */
//    private String srzcbz;

    /**
     * 金额
     */
//    @ExcelProperty("支出金额")
//    private BigDecimal je;

    @ExcelI18N(i18nkey = "支出金额")
    @ExcelProperty(value = "支出金额")
//    @ExcelProperty("借方发生额(支取)")
    private String jffse;
//    private BigDecimal jffse;

    @ExcelI18N(i18nkey = "收入金额")
    @ExcelProperty(value = "收入金额")
//    @ExcelProperty("贷方发生额(收入)")
    private String dffse;
//    private BigDecimal dffse;

    /**
     * 交易后余额
     */
    @ExcelI18N(i18nkey = "账户余额")
    @ExcelProperty(value = "账户余额")
    private String jyhye;
//    private BigDecimal jyhye;

    /**
     * 付款账号
     */
    @ExcelI18N(i18nkey = "对方账号")
    @ExcelProperty(value = "对方账号")
    private String fkzh;

    /**
     * 付款账号名
     */
    @ExcelI18N(i18nkey = "对方户名")
    @ExcelProperty(value = "对方户名")
    private String fkzhm;

    /**
     * 摘要说明
     */
    @ExcelI18N(i18nkey = "交易用途")
    @ExcelProperty(value = "交易用途")
    private String zysm;

    /**
     * 用途=摘要说明
     */
//    @ExcelProperty(value = "交易用途")
//    private String yt;

    public synchronized void changeExcelHead() throws NoSuchFieldException, IllegalAccessException {
        Field[] fields = ZgnyyhData.class.getDeclaredFields();
        for (int j = 0; j < fields.length; j++) {
            Field field = fields[j];
            if (field.isAnnotationPresent(ExcelI18N.class) && field.isAnnotationPresent(ExcelProperty.class)) {
                //获取NcxysData字段上的ExcelProperty注解实例
                ExcelI18N i18n = field.getAnnotation(ExcelI18N.class);
                ExcelProperty excel = field.getAnnotation(ExcelProperty.class);
                //获取 ExcelProperty 这个代理实例所持有的 InvocationHandler
                InvocationHandler i18nH = Proxy.getInvocationHandler(i18n);
                InvocationHandler excelH = Proxy.getInvocationHandler(excel);
                // 获取 AnnotationInvocationHandler 的 memberValues 字段
                Field i18nF = i18nH.getClass().getDeclaredField("memberValues");
                Field excelF = excelH.getClass().getDeclaredField("memberValues");
                // 因为这个字段事 private final 修饰,所以要打开权限
                i18nF.setAccessible(true);
                excelF.setAccessible(true);
                // 获取 memberValues
                Map i18nValues = (Map) i18nF.get(i18nH);
                Map excelValues = (Map) excelF.get(excelH);
                // 修改 value 属性值
                Object i18nO = i18nValues.get("i18nkey");
                Object excelOS = excelValues.get("value");
                if (i18nO != null && excelOS != null) {
                    String HEAD = (String) i18nO;//这里取到的就是@ExcelProperty的value值
                    PropertyResourceBundle res = (PropertyResourceBundle) PropertyResourceBundle.getBundle("excel"); // properties 文件名
                    switch (HEAD) {
                        case "会计日期":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jysj")});
                            break;
                        case "支出金额":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jffse")});
                            break;
                        case "收入金额":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.dffse")});
                            break;
                        case "账户余额":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jyhye")});
                            break;
                        case "对方账号":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.fkzh")});
                            break;
                        case "对方户名":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.fkzhm")});
                            break;
                        case "交易用途":
                            excelValues.put("value", new String[]{res.getString("excel.zgnyyh.zysm")});
                            break;
                    }
                }
            }
        }
    }

}

只需要在EasyExcelFactory.read之前调用changeExcelHead()方法即可从配置文件读取excel表头:

private ResponseEntity readExcelData(MultipartFile file) {
        try {
            DataListener2<ZwWyjymx> listener = new DataListener2<ZwWyjymx>();
            byte [] byteArr=file.getBytes();
            PropertyResourceBundle res = (PropertyResourceBundle)PropertyResourceBundle.getBundle("excel");
            Integer row = Integer.valueOf(res.getString("excel.zgnyyh.row"));
            new Data().changeExcelHead();
            InputStream inputStream = new ByteArrayInputStream(byteArr);//MultipartFile转为InputStream
//            ExcelReader excelReader = EasyExcelFactory.read(inputStream, null, listener).headRowNumber(5).build();
            ExcelReader excelReader = EasyExcelFactory.read(inputStream, Data.class, listener).headRowNumber(row).build();
            excelReader.readAll();
            List<ZwWyjymx> listMap = listener.getDatas();//取excel解析后的数据
            excelReader.finish();
            return ResponseEntity.ok(new Result(ResponseConstant.SUCCESS_CODE, ResponseConstant.PARSE_SUCCESS_MSG, listMap));
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, ResponseConstant.SERVER_ERROR_MSG, null));
            //读取文件出错的处理逻辑
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, "配置表头读取失败", null));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, "配置表头读取失败", null));
        }
    }

 注意:上面的配置文件虽然在idea中设置了.properties的文件格式utf-8,但当鼠标点击文件内容后在idea中其格式依然为ISO-8859-1,所以

(PropertyResourceBundle) PropertyResourceBundle.getBundle("excel").getString("excel.zgnyyh.jysj")就能取到配置文件的中文;
但当鼠标点击文件内容后发现格式已经为utf-8了,就要做如下变动
(PropertyResourceBundle) PropertyResourceBundle.getBundle("excel").getString("exce.zggsyh.jysj").getBytes("ISO-8859-1"),"UTF-8")取到的中文才不会乱码。
idea中设置文件编码格式和查看具体文件编码如下:

 

上面的方式读取的配置文件是在打包是会打在jar包里

 *************************************************************************************************************************************************************

下面的方式读取的配置文件只需要(未打包时:放在项目根目录下面;打jar包时:放在jar包同级目录下)

放在jar包同级目录下的配置文件读取方式:

//2022年2月21日
Properties properties = new Properties();
//优先使用外部配置文件 路径为 jar包所在目录System.getProperty("user.dir")即读取到jar包同级目录或者未打包前的项目根目录
        String path = System.getProperty("user.dir")+"/"+"excel.properties";
File file = new File(path);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
properties.load(fis);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//读取配置文件中具体参数
Integer row = Integer.valueOf(new String(properties.getProperty("excel0506.zggsyh.row").getBytes("ISO-8859-1"),"UTF-8"));

 

 

posted @ 2022-02-16 14:46  我不是习小贵  阅读(14435)  评论(0编辑  收藏  举报