深入剖析 EasyExcel 组件原理与应用

[复制链接]
发表于 2025-12-21 03:57:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
✨深入剖析 EasyExcel 组件原理与应用✨

官方:EasyExcel官方文档 - 基于Java的Excel处置惩罚工具 | Easy Excel 官网
  在一样平常的 Java 开发工作中,处置惩罚 Excel 文件的导入导出是极为常见的需求。  本日,咱们就一起来深入相识一款非常实用的操纵 Excel 的组件 ——EasyExcel,看看它究竟有着怎样的神奇之处,能让浩繁开发者青睐有加。   
  一、弁言

  想必各人都知道,在 Java 范畴中,Apache POI 是处置惩罚 Excel 文件的老牌工具了。但随着业务发展,面对越来越大的 Excel 文件读写需求时,POI 暴袒露了一些诸如内存溢出(OOM)等标题,利用起来稍显吃力。而 EasyExcel 的出现,很好地补充了这些不敷,它基于 POI 举行了优化封装,为我们提供了更加轻便高效的 Excel 处置惩罚方式。接下来,咱们就具体分析一下 EasyExcel 的原理以及它的具体应用。  二、EasyExcel 与 Apache POI 的渊源

  EasyExcel 着实是站在 Apache POI 这个 “巨人的肩膀” 上发展起来的。Apache POI 基于 OOXML(Office Open XML)尺度(像 xlsx、docx、pptx 等以指定格式的 xml 为根本并以 zip 格式压缩的文件)和 OLE2 尺度(包罗 xls、doc、ppt 等二进制格式的文件),只要符合上述尺度的文件它都能举行读写操纵。
  对于 xlsx 文件来说,它基于 OOXML 尺度,可以大概解压成对应的 xml 文件,在剖析后的 xml 文件里,我们重点关注 sharedStrings.xml 与 sheet1.xml 这两个 xml 节点,由于内里存放着我们想要处置惩罚的 Excel 内容。
  不外,POI 在处置惩罚 Excel 时有传统的 POM 剖析和 SAX 剖析两种方式。传统的 POM 剖析会把 Excel 中的全部 XML 节点剖析成一棵 DOM 树,整棵 DOM 树加载进内存,如许做固然方便对每个 XML 节点举行随机访问,但很轻易导致内存溢出征象,像仅仅 3 列的 Excel 文件在 7 万行左右就大概出现内存溢出标题。
  而 SAX 剖析则差异,它接纳边读取边处置惩罚的方式操纵 XML,逐行扫描 XML 文档,碰到标签时触发剖析处置惩罚器,进而触发相应的事故 Handler。这种方式内存占用小、服从高,但 POI 官方提供的 API 过于繁琐,利用起来步调繁多,好比读取一个 Excel 文件,要先将 xlsx 格式的 Excel 文件剖析成 OPCPackage 对象,再创建 XSSFReader 对象来剖析获取对应 xlsx 下的 xml 内容,想要处置惩罚还得进一步创建内容处置惩罚器等等,着实有些贫困。  




三、EasyExcel 的原理分析

(一)焦点架构与流程

  在 EasyExcel 中,有一个焦点的类叫 ExcelAnalyserImpl,它就像是整个操纵的调治中心。内里包罗了 AnalysisContext 类(分析上下文,存放对应的文件 Inputstream 跟 AnalysisEventListener 事故监听处置惩罚器等)和 ExcelReadExecutor 类(默认是 XlsxSaxAnalyser 类,焦点方法是 parseXmlSource (),负责逐行 SAX 剖析 Excel)。
  当 XlsxSaxAnalyser 剖析类实行剖析方法后,会调用 AnalysisEventProcessor 实行对应的事故方法,而在这个 processor 里真正实行操纵的就是对应的事故监听器啦。官方默认提供了一个事故监听器,能把 Excel 剖析成 BeanMap 的情势,然后根据我们传入的实体类,返回给我们想要的实体类对象。要是我们有定制化的功能需求,那就须要去相识这个监听器的焦点方法了哦。
  以下是一个简单的示例代码,展示怎样利用 EasyExcel 读取 Excel 文件并将数据转换为自界说对象(假设我们有一个 User 实体类,包罗 name 和 age 等属性):
         
  1. import com.alibaba.excel.EasyExcel;
  2. import com.alibaba.excel.context.AnalysisContext;
  3. import com.alibaba.excel.event.AnalysisEventListener;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. // 自定义监听器,用于处理读取到的数据
  9. class UserDataListener extends AnalysisEventListener<User> {
  10.     private List<User> userList = new ArrayList<>();
  11.     // 每解析一行数据就会调用此方法
  12.     @Override
  13.     public void invoke(User user, AnalysisContext analysisContext) {
  14.         userList.add(user);
  15.     }
  16.     // 全部解析完成后调用此方法
  17.     @Override
  18.     public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  19.         // 这里可以对读取到的所有数据进行后续操作,比如存入数据库等
  20.         System.out.println("共读取到 " + userList.size() + " 条用户数据");
  21.     }
  22.     public List<User> getUserList() {
  23.         return userList;
  24.     }
  25. }
  26. public class EasyExcelReadExample {
  27.     public static void main(String[] args) throws IOException {
  28.         String filePath = "your_excel_file_path.xlsx";  // 替换为实际的 Excel 文件路径
  29.         // 读取 Excel 文件,第二个参数是自定义的监听器
  30.         EasyExcel.read(new FileInputStream(filePath), User.class, new UserDataListener()).sheet().doRead();
  31.     }
  32. }
复制代码
       注解:


  • 在上述代码中,起首界说了 UserDataListener 类,它继续自 AnalysisEventListener,并重写了 invoke 和 doAfterAllAnalysed 方法。invoke 方法用于在每剖析一行 Excel 数据时将其封装成 User 对象并添加到 userList 中,而 doAfterAllAnalysed 方法则在整个 Excel 文件剖析完成后实行,可以在这里举行一些后续的数据处置惩罚操纵,好比将数据批量存入数据库等。
  • 在 EasyExcelReadExample 类的 main 方法中,通过 EasyExcel.read 方法来启动 Excel 文件的读取流程,传入文件输入流、要转换的目的对象范例(这里是 User 类)以及自界说的监听器,然后调用 sheet 和 doRead 方法完成读取操纵。

(二)关键方法剖析

1. doRead () 方法

  doRead () 方法实际调用过程还挺故意思的,它先是调用了 ExcelReader 中的 read 方法与 finish 方法。read 方法实际调用了 Executor 中的 execute 方法,这个 execute 方法里会调用前面提到的焦点方法 parseXmlSource 剖析 excel,而且在一个 sheet 中全部数据读取完后,会调用事故调治器的 endSheet 方法,让每一个监听器实行对应的 doAfterAllAnalysed 方法。而 finish 方法则负责对读取过程持有容器中流的内容输出,之后整理存储的缓存,把开启的相应的流关闭。  2. doWrite () 方法

  doWrite () 方法同样调用了 Writer 中的 write 方法和 finish 方法,这里的 finish 方法作用和读操纵里雷同哦。write 方法实际调用的是 Builder 中的 addContent 方法,在 addContent 方法里又会调用 Executor 中的 add 方法,针对传入的列表,逐个对象实行 addOneRowOfDataToExcel 方法举行逐行写入。在这个过程中,无论是创建行对象前后,还是添补完数据之后,我们都可以自界说处置惩罚器对流程举行相应的处置惩罚呢,非常机动。
  以下是一个利用 EasyExcel 写入 Excel 文件的示例代码,假设我们要将一个 List<User> 数据写入到 Excel 中:
         
  1. import com.alibaba.excel.EasyExcel;
  2. import com.alibaba.excel.write.metadata.WriteSheet;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. class User {
  6.     private String name;
  7.     private int age;
  8.     // 构造函数、Getter 和 Setter 方法省略,可根据实际情况补充完整
  9.     public User(String name, int age) {
  10.         this.name = name;
  11.         this.age = age;
  12.     }
  13. }
  14. public class EasyExcelWriteExample {
  15.     public static void main(String[] args) {
  16.         List<User> userList = new ArrayList<>();
  17.         userList.add(new User("张三", 25));
  18.         userList.add(new User("李四", 30));
  19.         String filePath = "output_excel_file.xlsx";  // 输出的 Excel 文件路径
  20.         // 这里使用 EasyExcel 的 write 方法开始写入操作
  21.         EasyExcel.write(filePath, User.class).sheet("用户信息表").doWrite(userList);
  22.     }
  23. }
复制代码
       注解:


  • 在这个示例中,先界说了 User 类来表现要写入 Excel 的数据对象,包罗 name 和 age 等属性(这里省略了部门通例的方法,实际利用中需增补完备)。
  • 在 EasyExcelWriteExample 类的 main 方法中,创建了一个 List<User> 集归并添加了一些示例数据。然后通过 EasyExcel.write 方法启动写入流程,传入输出文件路径和要写入的数据对象范例(User 类),接着指定 sheet 名称,末了调用 doWrite 方法并传入数据列表,如许就可以将数据乐成写入到指定的 Excel 文件中啦。

四、EasyExcel 的性能与易用性上风

(一)性能上风

  通过官方给出的结果图可以看到,EasyExcel 仅用 16M 内存在 23 秒内就能读取 75M(46W 行 25 列)的 Excel 文件,相比之下,POI 读取内存要用到 100M 往上了,读取时间更是没法比,可见在性能方面,EasyExcel 是遥遥领先呀。这得益于它基于事故机制逐行扫描数据,对数据逐行处置惩罚后,只要对象不被引用,就会被 JVM 快速垃圾接纳,从而有效克制了 OOM 标题。   
  (二)易用性上风

  利用 EasyExcel 举行文件的导入导出,相比 POI 的流程那但是简化了一大截呢,只要短短几行代码就可以轻松实现 Excel 的导入导出。这对于咱们开发者来说,简直太友爱了,能大大进步开发服从呀。   五、EasyExcel 中的操持模式 个人明确

(一)工厂模式

  EasyExcel 里的 EasyExcelFactory 类就运用了工厂模式哦。这个类拥有许多对应方法的差异入参的变体,终极目的都是为了根据差异的入参构造对应的 ExcelWriter/ReaderBuilder 对象,让代码调用起来轻便又雅观呢。 (二)观察者模式(也叫发布 - 订阅模式)

  通过事故监听器的机制,实现了雷同观察者模式的结果。当 Excel 文件剖析过程中碰到行、单位格等环境时会触发事故,然后通过自界说监听器来处置惩罚数据,各个监听器就像是观察者一样,等待着对应的事故发生然后实行相应的操纵。 (三)模板方法模式

  在剖析和写入等流程中,界说了一些模板化的方法,差异的实现类可以按照这些模板去扩展和定制具体的业务逻辑,包管了团体流程的规范性和可扩展性。 (四)装饰器模式

  在写样式等方面运用了装饰器模式,方便我们对 Excel 的样式等举行个性化的装饰和处置惩罚,让天生的 Excel 文件更加符合实际业务需求。  六、实际应用案例

  在实际项目中,EasyExcel 发挥着巨大的作用呢。好比说,我曾经须要从 Excel 表格中批量导入用户信息到 MySQL 数据库里。假如利用 POI,不但操纵复杂,而且面对稍大一点的 Excel 文件就轻易出现内存溢出标题。而选择 EasyExcel 后,它简单易用,性能又良好,更紧张的是可以大概节省内存、办理大文件内存溢出标题。像一个 3M 的 excel 文件,用 POI sax 剖析依然须要 100M 左右内存,改用 easyexcel 后可以低沉到几 M,而且再大的 excel 文件也不会出现内存溢出啦。对于数据量小的文件,我接纳同步模式一次性获取全部表格数据并存储到 List 中;对于数据量大的文件,则接纳自界说 Listener 的方式异步逐行读取 Excel 并分批插入到数据库中,非常方便高效。
  七、总结

  总的来说,EasyExcel 作为一款强盛的 Excel 处置惩罚组件,在 Apache POI 的根本上举行了优化和封装,无论是在性能、易用性还是功能扩展性上都有着精彩的体现。通过运用多种操持模式,让它更加机动且易于利用,在实际项目中可以大概帮我们轻松应对各种 Excel 文件的读写需求,大大进步了开发服从,也镌汰了由于内存溢出等标题带来的烦恼。盼望各人在之后的开发工作中,假如碰到 Excel 处置惩罚干系的业务,不妨试试 EasyExcel 哦,信托它会给你带来意想不到的惊喜。
  以上就是本次关于 EasyExcel 的全部内容分享啦,各人假如有任何疑问大概利专心得,欢迎在批评区留言互换呀。
以为有效的话可以点点赞 (*/ω\*),支持一下。
假如乐意的话关注一下。会对你有更多的资助。

每天都会不定时更新哦  >人<  。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表