一:使用场景
在日常的系统开发中,系统支持批量数据的操作是一个很常见的功能,其中,最常用的方式是使用excel表格对数据进行批量添加、删除,如:批量新建订单、批量添加商品等。
二:技术选型
现在市面上有很多技术实现来支持excel数据解析如OI、JXL等,但是,这些技术或多或少都存在着一些问题,下面进行具体分析/p>
(一)OI
POI是目前使用最多的用来做excel解析的框架,但这个框架还存在在这个许多问题。现在使用POI技术来解析excel文件的,大多数都是使用到它的userMode模式,好处是上手比较简单,而且网上比较多封装好的代码,虽然复制一下就可以运行,这个对于数据量不大的文件的时候是可以使用,但是当数据量大的时候会存在巨大隐患。
1、userMode模式存在着一个巨大的问题就是内存消耗很大,一个几兆的文件解析需要上百兆的内存,当并发量大的时候就会容易出现OOM(内存溢出)或者频繁进行fullGC回收),导致程序执行缓慢甚至崩溃
2、如果有深入了解过POI的会发现,其他它针对这个情况提供了一种叫SAX的模式,但是,这种模式相对复杂,且对excel03版本和07版本不兼容,两个版本的数据存储方式不一样,所以解析也不一样,这样需要同个功能需要进行两套代码开发,时间周期长,且不易于维护。
3、在大并发情况下,POI还存在着一些未知的错误,如果需要POI团队修复,周期不确定。
JXL
它是纯javaAPI,在跨平台上表现得非常完美,代码可以再windows或者Linux上运行而无需重新编写,但是它也存在着许多缺点。
1、效率低,格式支持比POI还少。
2、支持Excel95-的所有版本,但是excel以后的版本暂时不支持。
(三)EasyExcel(推荐使用)
阿里巴巴出的产品,相信看到这里很多人应该更有信心(毕竟阿里出的东西还是很有质量保障滴)。它是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel,选择使用它有以下原因:
1、开源,代码放在github上,有问题随时issue
2、解决了POI解析excel非常耗费内存的问题,它是通过磁盘存储,一行一返回,最大程度解决了内存占用大的问题。
3、社区活跃度高,网上的相关文档也比较多。
(四)POI解析模式和EasyExcel解析模型图
三:常用API介绍
(一)监视器(不能被Spring容器管理,每次读取Excel都需要新new一个,如果需要使用Spring容器对象,则通过构造函数传入)/p>
由于默认一行行地读取excel,所以需要创建excel一行一行的回调监听器(这个是必须实现的,所以我们要兼容所有的对象,监听器的泛型使用Object类型)
(二)读Excel/p>
1、EasyExcel.read(...)---》它有三个重载的方法
2、sheet()--》指定读取的sheet,doRead--》执行读取数据的操作
3、ExcelReader.readAll()--》执行读取Excel文件中的所有sheet
4、ExcelReader实例.finish()--》完成读取操作,并关闭流(一定要注意关闭流,因为easyExcel是使用磁盘的方式进行数据解析,所以解析过程中会创建临时文件,如果不关闭,最后可能会导致磁盘崩溃)
(三)写Excel/p>
1、EasyExcel.write(...)---》它有六个重载的方法
2、writeSheet()---》向excel文件中的sheet写入数据
3、ExcelWriter.write(...)---》插入sheet到excel文件中,这样就完成了数据写入,实际上就是嵌套一样,先将数据写入到sheet,再将sheet插入到excel中
4、ExcelWriter实例.finish()--》完成写入操作,并关闭流(一定要注意关闭流,因为easyExcel是使用磁盘的方式进行数据解析,所以解析过程中会创建临时文件,如果不关闭,最后可能会导致磁盘崩溃)
(四)常用注解
1、
ExcelProperty:作用在excel表数据对应的JAVA实体上,有以下属性
/p>
(1):value--指定导出时该字段对应的标题名称,或者是读取时匹配excel表格中表头的名称,符合则将表头中对应的数据填充到此处,如果这个名称存在多个,只能读取到一个。
(2):index--指定该字段和excel文件的哪一列对应,默认是0,不推荐和value属性同时指定,如果需要指定,那么value的值最好指定为导出数据对应表头的标题名,index的值则指定为读取excel文件时该字段属性对应的列的位置。
(3):converter属性则是指定对应的转换器,可以自己书写一个转换器,在读取数据的时候进行对数据的格式化,如:给每一列数据都加上自己自定义的东西
2、
ExcelIgnoreUnannotated:默认情况下Java类中的所有属性都添加读写,在类上面加入ExcelIgnoreUnannotated注解,加入这个注解后只有加了ExcelProperty才会参与读写。
3、
ExcelIgnore:被标注的属性不参加Excel的读写,相当于直接省略。
四:实战
(一):添加依赖
//easyExcel坐标dependencygroupId