java导出excel最佳实践,java大文件excel避免OOM(内存溢出)_第1页
java导出excel最佳实践,java大文件excel避免OOM(内存溢出)_第2页
java导出excel最佳实践,java大文件excel避免OOM(内存溢出)_第3页
java导出excel最佳实践,java大文件excel避免OOM(内存溢出)_第4页
java导出excel最佳实践,java大文件excel避免OOM(内存溢出)_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、产品需求产品经理需要导出一个页面的所有的信息到EXCEL文件。需求分析对于 excel 导出,是一个很常见的需求。 最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件。 客户体验 & 服务性能? 客户体验 如果导出的文件比较大,比如几十万条数据,同步导出页面就会卡主,用户无法进 行其他操作。? 服务性能导出的时候,任务比较耗时就会阻塞主线程。 如果导出的服务是暴露给外部(前后端分离),这种大量的数据传输十分消耗性能。 解决方案使用异常处理导出请求,后台 MQ 通知自己进行处理。MQ 消费之后,多线程处理 excel 文件导出,生成文件后上传到 FTP 等文件服务器。

2、前端直接查询并且展现对应的任务执行列表,去 FTP 等文件服务器下载文件即可。EXCELS出需要考虑的问题OOM正常的 poi 在处理比较大的 excel 的时候,会出现内存溢出。 网上的解决方案也比较多。比如官方的SXSSF (Sinee POI 3.8 beta3解决方式。或者使用封装好的包1. easypoi ExeelBatehExportServer2. hutool BigExeelWriter原理都是 强制使用 xssf 版本的 Excel你也可以使用easyexcel,当然这个注释文档有些欠缺,而且设计的比较复杂,不 是很推荐。我这里使用的是 hutool BigExcelWr

3、iter , 懒得自己再写一遍。FULL GC如果一次查询 100W 条数据库,然后把这些信息全部加载到内存中,是不可取的。 建议有 2 个:1. 限制每一次分页的数量。比如一次最多查询 1w 条。分成 100 次查询。(必须)2. 限制查询得总条数。比如限制为最多 10W 条。(根据实际情况选择) 虽然使用者提出要导出类似于 3 个月的所有信息,但是数量太多,毫无意义。 (提 出者自己可能体会不到 )尽量避免FULL-GC的情况发生,因为目前的所有方式对于 excel的输出流都会占用 内存, 100W 条很容易导致 FULL-GC。数据库的压力 去数据库读取的时候一定要记得分页,免得给数据库

4、太大的压力。 一次读取太多,也会导致内存直线上升。比如 100W 条数据,则分成 100 次去数据库读取。网络传输传统的 excel 导出,都是前端一个请求,直接 HTTP 同步返回。导出 100W 条,就 在那里傻等。这客户体验不友好,而且网络传输,系统占用多种问题。 建议使用异步处理的方式,将文件上传到文件服务器。前端直接去文件服务器读取。 编程的便利性对于上面提到的工具,比如 Hutool,在表头的处理方面没法很方便的统一。你可以自己定义类似于 easypoi/easyexcel 中的注解,自己反射解析。 然后统一处理表头即可。lExcel方便优雅的excel框架特性?00的方式操作ex

5、cel,编程更加方便优雅。?sax模式读取,SXSS模式写入。避免excel大文件00M。? 基于注解,编程更加灵活。?写入可以基于对象列表,也可以基于 Map,实际使用更加方便。? 设计简单,注释完整。方便大家学习改造。 后期特性? 读取跳过空白行? excel 样式相关的注解开发创作缘由实际工作和学习中, apache poi 操作 excel 过于复杂。 近期也看了一些其他的工具框架:? easypoi? easyexcel? hutool-poi都或多或少难以满足自己的实际需要,于是就自己写了一个操作 excel 导出的工具快速开始 引入 Jar 使用 maven 管理。<dep

6、endency><groupId> com.github.houbb </groupId><artifactId> iexcel </artifactId><version> 0.0.2 </version></dependency>说明2003版本的excel2007版本的excelSXSSFExcelWriterExcelUtil.getBigExcelWriter()大文件excel,避免OOM定义对象你可以直接参考ExcelUtilTest.java定义一个需要写入/读取的excel对象? Exc

7、elFieldModel.java只有声明了 ExcelField的属性才会被处理,使用说明:ExcelFieldpublic class ExcelFieldModel ExcelFieldprivate Str ing n ame;ExcelField (headName ="年龄”)private Str ing age;ExcelField (mapKey = "EMAIL" , writeRequire = false , readRequire = alse )privateStri ng email;ExcelField (mapKey = &quo

8、t;ADDRESS", headName ="地址 ”,writeRequire = true )privateStri ng address;/getter and setter写入例子lExcelWriter的实现IExcelWriter有几个实现类,你可以直接 new或者借助ExcelUtil 类去创建。lExcelWriter实现类 ExcelUtil如何创建HSSFExcelWriter ExcelUtil.getO3ExcelWriter()XSSFExcelWriterExcelUtil.getO7ExcelWriter()IExcelWriter 接口说明

9、写入到2003? excelWriter03Test()一个将对象列表写入2003 excel文件的例子。* 写入到 03 excel 文件*/Test public void excelWriter03Test () / 待生成的 excel 文件路径final String filePath = "excelWriter03.xls"/ 对象列表buildModelList ();List<ExcelFieldModel> models =try (IExcelWriter excelWriter = ExcelUtil. get03ExcelWriter

10、(); OutputStream outputStream =new FileOutputStream(filePath) / 可根据实际需要,多次写入列表 excelWriter. write (models);/ 将列表内容真正的输出到 excel 文件 excelWriter. flush (outputStream); catch (IOException e) throw new ExcelRuntimeException (e);? buildModelList()* 构建测试的对象列表* return 对象列表 */buildModelList () new ArrayList&

11、lt;>();new ExcelFieldModel ();private List<ExcelFieldModel> List<ExcelFieldModel> models = ExcelFieldModel model =model. setName (" 测试 1 号 ");model. setAge ( "25" );model. setEmail ( "123" ); model. setAddress (" 贝克街 23 号");ExcelFieldModel model

12、Two = new ExcelFieldModel (); modelTwo.setName ( " 测试 2 号");modelTwo. setAge ( "30" );modelTwo. setEmail ( "125" );modelTwo. setAddress ( " 贝克街 26 号");models.add (model);models.add (modelTwo);return models;ExcelReaderExcelUtil.getExcelReader()小文件的excel读取实现SaxO

13、3ExcelReaderExcelUtil.getBigExcelReader()大文件的2003 excel读取实现Sax07ExcelReaderExcelUtil.getBigExcelReader()大文件的2007 excel读取实现一次性写入到2007 excel有时候列表只写入一次很常见,所有就简单的封装了下:*只写入一次列表*其实是对原来方法的简单封装*/Testpublic void on ceWriterA ndFlushO7Test () II待生成的excel文件路径finalStri ng filePath ="on ceWriterA ndFlushO7.

14、xlsx"/对象列表List<ExcelFieldModel> models =buildModelList ();/对应的excel写入对象IExcelWriter excelWriter = ExcelUtil.getO7ExcelWriter ();/只写入一次列表ExcelUtil.on ceWriteA ndFlush(excelWriter, models, filePath);读取例子excel读取时会根据文件名称判断是哪个版本的exceLlExcelReade 的实现IExcelReader有几个实现类,你可以直接 new或者借助ExcelUtil 类去创

15、建IExcelReader 实现说明类ExcelUtil如何创建IExcelReader 接口说明 excel读取的例子/*读取测试*/Testpublic void readWriterTest () File file =new File( "excelWriterO3.xls" );IExcelReader<ExcelFieldModel> excelReader = ExcelUtil.getExcelReader (file);List<ExcelFieldModel> models = excelReader.readAll (Excel

16、FieldModel.class );System. out . println (models);ExcelField注解说明ExcelField 的属性说明如下:默认属性类型 值 说明mapKeyStri ngIlliheadNameStri ngIlli仅用于生成的入参为map时,会将map.key对应的 值映射到bean上。如果不传:默认使用当前字段 名称excel表头字段名称,如果不传:默认使用当前字 段名称writeRequire boolea n true readRequire boolea n trueexcel文件是否需要写入此字段excel文件是否读取此字段*lExcel

17、Writer 接口说明写出数据,本方法只是将数据写入Workbook中的Sheet,并不写出到文件<br><p>data中元素支持的类型有:<pre>1. Bean,既元素为一个 Bean,第一个Bean的字段名列表会作为首行,剩下的行为Bean的字段值列表,data表示多行<br>* </pre>* param data 数据* return this*/IExcelWriter write (Collectionv?> data);写出数据,本方法只是将数据写入Workbook中的Sheet,并不写出到文件<br>

18、;将map按照targetClass转换为对象列表应用场景:直接mybatis mapper查询出的map结果,或者其他的构造结果。param mapList map 集合param targetClass目标类型return this*/final ClassIExcelWriter write (Collection<Map<String, Object>> mapList, <?> targetClass);/*将 Excel Workbook 刷出到输出流*param outputStream 输出流 return this*/IExcelWriter flush (OutputStream outputStream);指定 sheet创建 IExcelWriter 的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论