写在前面
Java 后端程序员应该会遇到读取 Excel 信息到 DB 等相关需求,脑海中可能突然间想起 Apache POI 这个技术解决方案,但是当 Excel 的数据量非常大的时候,你也许发现,POI 是将整个 Excel 的内容全部读出来放入到内存中,所以内存消耗非常严重,如果同时进行包含大数据量的 Excel 读操作,很容易造成内存溢出问题
但 EasyExcel 的出现很好的解决了 POI 相关问题,原本一个 3M 的 Excel 用 POI 需要100M左右内存, 而 EasyExcel 可以将其降低到几 M,同时再大的 Excel 都不会出现内存溢出的情况,因为是逐行读取 Excel 的内容 (老规矩,这里不用过分关心下图,脑海中有个印象即可,看完下面的用例再回看这个图,就很简单了)
另外 EasyExcel 在上层做了模型转换的封装,不需要 cell 等相关操作,让使用者更加简单和方便,且看
简单读
假设我们 excel 中有以下内容:
我们需要新建 User 实体,同时为其添加成员变量
@Datapublic class User { /** * 姓名 */ @ExcelProperty(index = 0) private String name; /** * 年龄 */ @ExcelProperty(index = 1) private Integer age;}
你也许关注到了 @ExcelProperty 注解,同时使用了 index 属性 (0 代表第一列,以此类推),该注解同时支持以「列名」name 的方式匹配,比如:
@ExcelProperty("姓名")private String name;
按照 github 文档的说明:
不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
- 如果读取的 Excel 模板信息列固定,这里建议以 index 的形式使用,因为如果用名字去匹配,名字重复,会导致只有一个字段读取到数据,所以 index 是更稳妥的方式
- 如果 Excel 模板的列 index 经常有变化,那还是选择 name 方式比较好,不用经常性修改实体的注解 index 数值
所以大家可以根据自己的情况自行选择
编写测试用例
EasyExcel 类中重载了很多个 read 方法,这里不一一列举说明,请大家自行查看;同时 sheet 方法也可以指定 sheetNo,默认是第一个 sheet 的信息
上面代码的 new UserExcelListener() 异常醒目,这也是 EasyExcel 逐行读取 Excel 内容的关键所在,自定义 UserExcelListener 继承 AnalysisEventListener
@Slf4jpublic class UserExcelListener extends AnalysisEventListener { /** * 批处理阈值 */ private static final int BATCH_COUNT = 2; List list = new ArrayList(BATCH_COUNT); @Override public void invoke(User user, AnalysisContext analysisContext) { log.info("解析到一条数据:{}