alibaba easyExcel2.1.1 springboot新版使用教程(适用小白)

1 篇文章 0 订阅
1 篇文章 0 订阅

CSDN上的教程都太老了,特别是这个easyExcel大部分方法都过时了,而且鱼龙混杂,绝大部分是从各个地方copy过来的,总之学起来成本太高,太扎心了。

其实easyExcel的官网Demo写的都挺全的,但大神写的东西即便是有注释也是看的小白云里雾里,还有几个地方根本就没有说,反正我是一次又一次跳进了坑里,所以这边文章用以补充为主。easyExcel官方网址:https://github.com/alibaba/easyexcel

大家可以git下来用于学习。

首先我用的版本easyExcel2.1.1,springboot

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>easyexcel</artifactId>
   <version>2.1.1</version>
</dependency>

正文:

第一个坑,我之前用的旧版,后来才自己琢磨出来问题出在哪里,新版是向下兼容的所以可以用旧版(2.0之前)的语法,而且源码逻辑并没有太大改变,所以才出现了在旧版的问题延续到了新版

这个EasyExcelFactory.read()方法其实是默认在第二行读取的,即默认参数headRowNumber=1,但读取的是我的表头,会报com.alibaba.excel.exception.ExcelAnalysisException: Convert data 创建时间 to class java.util.Date error 错误,我一直以为是时间格式错误,没想到他是读取的我的表头,自然String类型的“创建时间”不能转换成Date类型的,所以新版easyExcel就要添加一个headRowNumber(2)方法,让他从第三行开始读取。

下面是我整个ServiceImpl的导入方法:

 /**
     * 导入 Excel(一个 sheet)到数据库 暂不支持update
     * 这里可以处理很多业务逻辑,比如传入的id不能重复,或者把插入失败的数据返回给客户端
     * @param excel 需要导入的excel
     * @param soldData Excel修改后Sold实体类
     * @param headLineNum 第一页sheet
     * @returnutil
     */
    @Override
    public Integer importSoldExcel(MultipartFile excel, SoldData soldData, int headLineNum) throws IOException {
        if (excel == null) {
            return 0;
        }
        // 解决反射调用service层,@Autowired注入失败 AnalysisEventListener()的invoke()  同时更容易接收返回数据
        AnalysisEventListener listener = new AnalysisEventListener<SoldData>() {
            /**
             * 这个每一条数据解析都会来调用
             * @param data
             * one row value. Is is same as {@link AnalysisContext#readRowHolder()}
             * @param context 解析数据
             */
            @Override
            public void invoke(SoldData data, AnalysisContext context) {
                LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
                //去重
                SoldEntity soldEntity = soldService.getOneByVin(data.getP_vin());
                if (soldEntity == null) {
                    list.add(data);
                }
                if (list.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    list.clear();
                }
            }

            /**
             * 所有数据解析完成了 都会来调用
             * @param context 解析数据
             */
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 这里也要保存数据,确保最后遗留的数据也存储到数据库
                saveData();
                LOGGER.info("所有数据解析完成!");
            }
        };
        EasyExcel.read(excel.getInputStream(), SoldData.class, listener).sheet().headRowNumber(2).doRead();
        return list.size();
    }

第二个问题确实就是时间格式的问题了,因为同事给的源数据是这种2020-01-16 15:36的,用yy-MM-dd hh:mm:ss 会报错,所以要改成@DateTimeFormat("yyyy-MM-dd HH:mm")这种

这是实体类啦,index是用来读取你Excel中第几列的,默认从是0从第一列开始,如果你有用不到的也要给他排序,因为没有index排序的会在导出的时候自动排在前面,当然你不做导出功能或者导出不用这个实体类的话就不用排序了。

最后,官方是继承了AnalysisEventListener<SoldData>自己写了一个监听类,然后在监听类里面写逻辑执行保存操作,我是直接重写了监听类里面的invoke()和doAfterAllAnalysed()方法。首先是因为监听类里面不能直接返回结果,还有就是带有注解的Bean(我的soldService)在监听类里是无效的,有两个解决方法,一种是在监听类初始化,一种是在ServiceImpl类中soldService传过去,但还要在自己写的监听类里面做相应的修改,同时这样就不能用重写方法+自己继承AnalysisEventListener的方式写了,必须重写全部方法或者只用监听类。

EasyExcel.read(excel.getInputStream(), SoldData.class, new SoldDataListener(soldService)).sheet().headRowNumber(2).doRead();

待续...

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值