前言
又写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 表列
极度化降低内存使用,使用简单
快速实践
我们先写个脚本轻轻感受模拟一下,被处理的数据需要的逻辑。假设是一个修复脚本。
你辛辛苦苦从几张离线表中一顿猛操作捞出了需要修复的问题数据,假设如下:
ok,数据有了,那就开始写修复脚本,我们先定义一个修复数据接口 FlushDataService
。
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;
@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;
@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;
@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);
}
}
测试一下
是不是效果还行,赶紧也试试吧,不过还是祈祷你们平时少出问题,毕竟你们都是专业的,BUG在所难免,重点是我们要有出现问题快速解决问题的能力。好了,我们下期见~
"我爱你" 三个字,讲出来只要三秒,解释要三小时,证明却要一辈子。
"bug" 三个字母,发现只要三秒,找到需要三小时,debug却要一辈子。
作者:橘松Java
共同学习,写下你的评论
评论加载中...
作者其他优质文章