SpringBoot + Excel 读写技术与实际问题解决


文章有很多不对的地方,敬请指正!!

一、背景

1.Excel使用

  1. 在业务系统开发中,常遇到录入数据,使用Excel导入数据到系统中。

2.Java 操作Excel的技术选型

  1. Apache POI
  2. Easy POI
  3. Easy Excel

3. 三种方式对比

1. Apache POI

  1. 导入导出的方式
  • HSSFoffice 2003专用格式,.xls;速度快,但行数受限制(65536)。
  • XSSFoffice 2007专用格式,.xlsx;速度慢,但不受行数限制,读写一次性写入内存,容易导致OOM
  • SXSSF 是XSSF API的兼容流式扩展,主要解决使用XSSF数据量大时内存溢出问题,支持导出大批量数据。
  1. 为什么会这样?
  • 几乎产品都是在不断的迭代中,会遇到各种瓶颈,如XSSF格式的.xlsx解决了HSSF格式的.xls,但又迎来了新的问题,由于XSSF形式时先将数据写入内存,在导入导出,因此当数据量大的时候,内存消耗大,就容易造成OOM(内存泄漏)。为了应对此种情况,SXSSF为了应对XSSF出现的问题,设定在内存中的条数最大值,当满足最大值时,先将其持久化逐步(分段)写入的方式,有效避免OOM。
  1. 优缺点
  • 完成业务代码量大,迁移重复代码多
  • 需求变更难以维护,定制化场景难度大。

2. Easy POI

  1. 产生
  • 这种方式基于Apache POI,又致力于解决Apache POI在实际业务中,需求不断变更的情况下,不易维护,比如在完成正常的导入导出功能后,添加表格样式,或者合并列,单元格等。不仅不断的修改代码,还造成代码积聚,在开发其他系统的情况下,copy之前的代码,使开发者非常烦恼,也使企业浪费了人力
  1. 优点
  • 主打功能:使一个未接触POI的人员快速便捷完成Excel导入、导出等功能
  • 抽取公共代码封装,除去了大量的重复工作。
  • 采用注解来完成定制化的工作,代码量的减少,极大的给程序员带来了便捷。
  • 写入内存原因,读写性能较好
  1. 缺点
  • 致力于 “easy” 的EasyPOI 采用DOM解析方式,将数据一次性读入内存,在平常数据量少,并发量低时没有任何问题,但数据量、并发量大的情况下仍然造成OOM。
  • 大数据导入导出时,采用SAX模式特定方法实现分段写入,解决OOM问题,但具有诸多局限性,且数量级达到(导入:10W以上,导出:几万到上百万)才有意义。

3. Easy Excel

  1. 优点
  • 与Easy POI类似,基于Apache POI深度二次开发,仍然采用注解简化开发,避免重复开发。
  • 采用SAX模式,一行一行的解析数据,即使高并发的情况下,仍然稳定。
  • 通过磁盘存储,极大程度的解决了POI消耗内存的问题,
  1. 缺点
  • 通过磁盘存储,读写性能较Easy POI低。
  • 对定制化的导出较Easy POI不够丰富。

4. 使用推荐

  1. 当数据量小,并发量低的情况下,且对于导出的Excel文件样式各种各样的情况下使用Easy POI,反之,使用EasyExcel。

二、Easy Excel使用(推荐)

1.使用

2.开发中的问题

  1. 在实际开发中,常常会自定义其监听器(不可托管于Spring),且在官方案例中,针对读取数据实体类型的不同定义大量的监听器,需解决?
  • 自定义公共监听器,采用泛型解决实体类型问题
  1. 如何处理数据量大的情况?在监听器中不可避免的操作数据
  • 采用分段处理方法避免OOM
  • 大致思路:维护一个存储读到转换为实体的成员变量列表 list、默认分段大小常量BATCH_COUNT,当读取到的数量>=BATCH_COUNT时,存入数据库,且清楚已存储数据list.clear(); 最后剩下的不足BATCH_COUNT的数据在全部解析完成的方法内存入数据库。
  1. 在读取数据中,通常会对读取到数据进行校验和存储,如何解决采用构造函数传入数据持久化实例,存储数据以及批量问题?
  • 可以使用判定型函数接口 Predicate<T> 来完成行数据的校验
  • 可以使用消费型函数接口 Consumer<T>来完成数据存储
  • 数据存储,在mybatis&mybatis-plus中采用批量插入解决性能问题
  1. 若希望将Easy Excel再次封装为常用的工具类,如何能应对数据校验Lambda校验函数、转换实体类型、以及对应的数据持久化类的多样性。
  • 大致思路(未检验):动态传入对应Class类实例,在SpringContext 上下文中利用Class类实例获取对应的Method,调用其invoke方法,完成数据存储。
  1. 监听器校验过程中的校验结果在真实业务开发中需要传回前端展示,如何解决?
  • 维护一个记录行数,改行数据的List成员变量存储数据
  1. 使用Easy Excel导出数据时,如何处理导出数据为多个实体组合,一对一、一对多的情况,例如一个订单多个产品,这样导出的数据订单的信息重复出现,如何实现单元合并?
  • 须在导出时注册一个写处理器,即处理单元格的策略。
  • 大致思路:将一对多关系嵌套属性平铺,且自定义注解标注主键、需合并的属性,具体的策略实施过程中使用反射技术获取需要属性上自定义注解,获取注解属性,根据主键标识判断是否行需要合并,是否合并标识判断是否合并字段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值