easy-excel:一款阿里开源解析excel框架

Java解析、生成Excel比较有名的框架有Apache、poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度地解决一些内存溢出的问题

前言

又写bug呢?当我们线上遇到bug的时候,可能需要修复数据,那么这时候怎么办呢?你很慌了,打开离线表一顿猛之后,得到了一份要修复的数据,然后写了一段修复脚本,准备发布修复一下时候,这时候问题来了,怎么解析数据呢,加载这份数据到内存里,然后依次读取修复吗?太慢啦。

这里介绍一款阿里开源解析excel框架 easy-excel

是什么

这里引用下官方的介绍

Java解析、生成Excel比较有名的框架有Apache、poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度地解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

能做什么

  • 数据的批量处理、解析
  • 支持自定义模型类字段映射 excel 表列
  • 极度化降低内存使用,使用简单

快速实践

我们先写个脚本轻轻感受模拟一下,被处理的数据需要的逻辑。假设是一个修复脚本。

你辛辛苦苦从几张离线表中一顿猛操作捞出了需要修复的问题数据,假设如下:

一款阿里开源解析excel框架"easy-excel"

ok,数据有了,那就开始写修复脚本,我们先定义一个修复数据接口 FlushDataService 。

/**
 * @创建人 : 掘金账号 "橘松Java"
 * @创建时间 2021/7/11
 * @描述 : 需要源码加QQ群[693961584]免费索取
 */
public interface FlushDataService {
    /**
     * 刷数据接口
     * @param index 为了扩展,定义刷数据文件索引
     */
    void flush(Integer index);
}

再定义Excel表头,修复表格数据需要的模型 ItemChannelExcel。注意这里的@ExcelProperty注解一定要标上,注解index属性则是你的excel表的列的索引。

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.Data;

/**
 * @创建人 : 掘金账号 "橘松Java"
 * @创建时间 2021/7/11
 * @描述 : 需要源码加QQ群[693961584]免费索取
 */
@Data
public class ItemChannelExcel extends BaseRowModel {

    @ExcelProperty(index = 0)
    private Long itemNo;

    @ExcelProperty(index = 1)
    private Long itemName;
}

这里需要写监听器ItemChannelExcelListener 继承 AnalysisEventListener 泛型类,写你的业务数据处理逻辑。

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @创建人 : 掘金账号 "橘松Java"
 * @创建时间 2021/7/11
 * @描述 : 需要源码加QQ群[693961584]免费索取
 */
@Service
public class ItemChannelExcelListener extends AnalysisEventListener<ItemChannelExcel> {

    private AtomicInteger totalHandleCount = new AtomicInteger(0);
    private AtomicInteger sucHandleCount = new AtomicInteger(0);
    private AtomicInteger failHandleCount = new AtomicInteger(0);

    @Override
    public void invoke(ItemChannelExcel channelExcel, AnalysisContext analysisContext) {
        System.out.println("正在处理的行row=="+channelExcel.getItemNo()+"==="+channelExcel.getItemName());

        //invoke rpc interface 这里mock
        try{
            //Result<Xxx> listItemRes = xxxService.listItems(Long shopId);
            //if(listItemRes.isSuccess()) {
            //    sucHandleCount.incrementAndGet();
            //}else{
            //    failHandleCount.incrementAndGet();
            //}
            sucHandleCount.incrementAndGet();
        }catch(Exception ex){
            failHandleCount.incrementAndGet();
        }final {
            totalHandleCount.incrementAndGet();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        //全部处理完成的回调函数
        System.out.println("本次一共处理的数据有"+ totalHandleCount+"条");
        System.out.println("本次成功处理的数据有" + sucHandleCount + "条");
        System.out.println("本次失败处理的数据有" + failHandleCount + "条");
    }

修复逻辑和模型都搞定了,接下来就该写实现类了 FlushDataServiceImpl,注意这里需要注入解析Excel监听器绑定起来,读取Excel指定文件源位置,以及解析模型和业务处理监听器。

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;

import java.io.InputStream;

/**
 * @创建人 : 掘金账号 "橘松Java"
 * @创建时间 2021/7/11
 * @描述 : 需要源码加QQ群[693961584]免费索取
 */
@service
public class FlushDataServiceImpl implements FlushDataService {

    @Resource
    private ItemChannelExcelListener itemChannelExcelListener;

    @Override
    public void flush(Integer index) {
        Class<? extends FlushDataServiceImpl> clazz = this.getClass();
        InputStream resourceAsStream = clazz.getResourceAsStream("/flush.xlsx");
        //这里创建Sheet对象 传1 主要是排查表头,因为excel第一行不需解析,读者按需要指定
        EasyExcelFactory.readBySax(resourceAsStream,new Sheet(1,1, ItemChannelExcel.class), itemChannelExcelListener);
    }
}

测试一下

一款阿里开源解析excel框架"easy-excel"

是不是效果还行,赶紧也试试吧,不过还是祈祷你们平时少出问题,毕竟你们都是专业的,BUG在所难免,重点是我们要有出现问题快速解决问题的能力。好了,我们下期见~

内容出处:,

声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。文章链接:http://www.yixao.net/share/25159.html

发表评论

登录后才能评论