• 通过反射,实现修改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"));
     
    
    
  • 相关阅读:
    PipeCAD 1.0.5 is Released!
    PipeCAD 管道ISO图
    PipeCAD设备图元
    PipeCAD 1.0.6 is Released!
    PipeCAD 1.0.3 is Released!
    PipeCAD 1.0.2 is Released!
    OpenCASCADE 曲线向曲面投影
    OpenCASCADE 曲面展开
    GEE Landsat 7数据缝隙填充
    流程图gojs 简单使用
  • 原文地址:https://www.cnblogs.com/xyg34/p/15900501.html
Copyright © 2020-2023  润新知