用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题。针对不同的Excel版本,要采用不同的工具类。HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx。
用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在64位中没有限制,但是在64位的系统中,性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式的Excel文件。
这里普及一下,在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量,这时对于百万级别数据,Excel肯定容纳不了,而且在计算机性能稍低的机器上测试,就很容易导致堆溢出。而当我升级到XSSF对象时,它可以直接支持excel2007以上版本,因为它采用ooxml格式。这时excel可以支持1048576条数据,单个sheet表就支持近104万条数据了,虽然这时导出100万数据能满足要求,但使用XSSF测试后发现偶尔还是会发生堆溢出,所以也不适合百万数据的导出。
现在我们知道excel2007及以上版本可以轻松实现存储百万级别的数据,但是系统中的大量数据是如何能够快速准确的导入到excel中这好像是个难题,对于一般的web系统,我们为了解决成本,基本都是使用的入门级web服务器tomcat,既然我们不推荐调整JVM的大小,那我们就要针对我们的代码来解决我们要解决的问题。在POI3.8之后新增加了一个类,SXSSFWorkbook,采用当数据加工时不是类似前面版本的对象,它可以控制excel数据占用的内存,他通过控制在内存中的行数来实现资源管理,即当创建对象超过了设定的行数,它会自动刷新内存,将数据写入文件,这样导致打印时,占用的CPU,和内存很少。但有人会说了,我用过这个类啊,他好像并不能完全解决,当数据量超过一定量后还是会内存溢出的,而且时间还很长。对你只是用了这个类,但是你并没有针对你的需求进行相应的设计,仅仅是用了,所以接下来我要说的问题就是,如何通过SXSSFWorkbook以及相应的写入设计来实现百万级别的数据快速写入。
v修改pom.xml
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency>
v添加controller
package com.demo.controller; import com.demo.pojo.UserDetails; import com.demo.service.UserService; import org.apache.poi.hssf.usermodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; import java.util.List; /** * Created by toutou on 2018/11/3. */ @Controller public class FileController { @Autowired UserService userService; @RequestMapping(value = "export") public void Export(HttpServletResponse response) throws IOException { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("信息表"); List<UserDetails> classmateList = userService.getUserDetails(); // 设置要导出的文件的名字 String fileName = "users" + new Date() + ".xls"; // 新增数据行,并且设置单元格数据 int rowNum = 1; // headers表示excel表中第一行的表头 在excel表中添加表头 String[] headers = { "id", "uid", "地址", "城市"}; HSSFRow row = sheet.createRow(0); for(int i=0;i<headers.length;i++){ HSSFCell cell = row.createCell(i); HSSFRichTextString text = new HSSFRichTextString(headers[i]); cell.setCellValue(text); } //在表中存放查询到的数据放入对应的列 for (UserDetails item : classmateList) { HSSFRow row1 = sheet.createRow(rowNum); row1.createCell(0).setCellValue(item.getId()); row1.createCell(1).setCellValue(item.getUid()); row1.createCell(2).setCellValue(item.getAddress()); row1.createCell(3).setCellValue(item.getCity()); rowNum++; } response.setContentType("application/octet-stream"); response.setHeader("Content-disposition", "attachment;filename=" + fileName); response.flushBuffer(); workbook.write(response.getOutputStream()); } }
原文地址:https://www.cnblogs.com/toutou/p/9857963.html