SpringBoot kombiniert mit einem POI-Datenbericht auf Millionenebene

Erweiterter POI-Bericht

Im vorherigen Artikel wurde eingeführt, dass Excel in zwei Versionen unterteilt werden kann: Excel2003 und Excel2007. Excel2003 verwendet HSSF-Objekte in POI. Ein Blatt erlaubt bis zu 65536 Datenelemente. Es kann verwendet werden, wenn weniger Daten verarbeitet werden, aber Excel2003 kann bei der Verarbeitung von Millionen von Daten sicherlich nicht berücksichtigt werden. ; Excel2007 verwendet XSSF-Objekte in POI, sodass ein Blatt höchstens 1048576 Daten speichern kann. Dies zeigt an, dass es Millionen von Daten unterstützen kann, es jedoch Probleme im tatsächlichen Betrieb geben kann. Der Grund dafür ist, dass die von POI-Berichten generierten Objekte Zellobjekte, Schriftobjekte werden nicht zerstört, was zu einem möglichen OO-Speicherüberlaufrisiko (OutOfMemoryError) führen kann.

Exportübersicht über Millionen Datenberichte

Besprechen Sie für den Export von Millionen von Excel-Daten grundsätzlich nur die Verwendung der Excel2007-Version. ApachePOI bietet drei Möglichkeiten, um den Import und Export großer Datenmengen zu lösen:

  • Benutzermodus: Der Benutzermodus verfügt über viele gekapselte Methoden, die einfach zu bedienen sind, jedoch zu viele Objekte erstellen und viel Speicher verbrauchen
  • Ereignismodus: Das Parsen von XML basierend auf SAX (Simple API for XML) ist eine Schnittstelle und ein Softwarepaket. Es ist eine Alternative zum XML-Parsen. Der Unterschied zum DOM-Parsen besteht darin, dass es Zeile für Zeile analysiert und nicht alle Daten gleichzeitig lädt. Der Speicher entspricht der Analyse beim Scannen.
  • SXSSF-Objekt: Wird zum Generieren einer großen Anzahl von Excel-Dateien verwendet, hauptsächlich mit temporärem Speicherplatz zum Generieren von Excel

    Export von Millionen von Daten

Bedarfsanalyse

Im Internet-Zeitalter werden häufig Millionen von Daten generiert, und es gibt verschiedene Gründe für den Datenexport

Lösung

  • 1. Denkanalyse:

Wenn Sie das XSSFWORK-Objekt von POI zum Exportieren von Excel-Berichten verwenden, werden alle Daten gleichzeitig in das Zellenobjekt übertragen und im Speicher gespeichert. Wenn alle Zellen erstellt wurden, werden sie gleichzeitig zum Export in Excel geschrieben. Bei Erreichen der Millionen von Daten exportieren, mit der kontinuierlichen Erstellung von Zellenobjekten, immer mehr Daten im Speicher, bis OOM. Das SXSSFWORK-Objekt von POI wird speziell aus Excel exportiert, um große Datenmengen zu verarbeiten.

2. Prinzipanalyse:

Wenn Sie das SXSSFWork-Objekt instanziieren, können Sie die Anzahl der im Speicher generierten POI-Objekte angeben (Standard 100). Sobald die Anzahl der Speicherobjekte die angegebene Anzahl erreicht, werden die Daten im Speicher auf die Festplatte geschrieben und die Daten im Speicher können zerstört werden Schleife, bis der Excel-Export abgeschlossen ist

Code

Nehmen Sie als Beispiel Benutzerdaten

In FileUtil hinzufügen

Einige kleinere Änderungen am vorherigen vorgenommen

package com.cn.greemes.common.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 文件操作
 */
public class FileUtil {

    public static final String SYS_TEM_DIR =System.getProperty("java.io.tmpdir")+ File.separator;

    public  void downloadExcel(List<Map<String, String>> list, HttpServletResponse response) throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        File file = new File(tempPath);
        BigExcelWriter writer = ExcelUtil.getBigWriter(file);
        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(list, true);
        SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
        //上面需要强转SXSSFSheet  不然没有trackAllColumnsForAutoSizing方法
        sheet.trackAllColumnsForAutoSizing();
        //列宽自适应
       // writer.autoSizeColumnAll();
        //response为HttpServletResponse对象
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
        ServletOutputStream out = response.getOutputStream();
        // 终止后删除临时文件
        file.deleteOnExit();
        writer.flush(out, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }

    public  void downloadExcelBySXSSF(List<Map<String, String>> list, HttpServletResponse response) throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        File file = new File(tempPath);
        //2.创建工作簿
         SXSSFWorkbook workbook = new SXSSFWorkbook();
        //3.构造sheet
        Sheet sheet =workbook.createSheet();
        //创建表头
        Row row = sheet.createRow(0);
        Map<String,String> mapfirst = list.get(0);

        String listHead = null;
        AtomicInteger headersAi = new AtomicInteger();

        for (String key : mapfirst.keySet()) {
           Cell cell = row.createCell(headersAi.getAndIncrement());

           cell.setCellValue(key);
        }
        AtomicInteger datasAi = new AtomicInteger(1);
        Cell cell =null;
        for(Map<String, String> map : list){
            Row dataRow = sheet.createRow(datasAi.getAndIncrement());
            int i=0;
            for (String key : map.keySet()) {
                Cell cell1 = dataRow.createCell(datasAi.getAndIncrement());
                String value= (String)map.get(key);
                cell = dataRow.createCell(i);
                cell1.setCellValue(value);
                i++;
            }
        }
        String fileName = URLEncoder.encode("用户信息.xlsx", "UTF-8");
        response.setContentType("application/octet-stream");
        response.setHeader("content-disposition", "attachment;filename=" + new
                String(fileName.getBytes("ISO8859-1")));
        response.setHeader("filename", fileName);
        workbook.write(response.getOutputStream());

    }
}

Im Controller konfigurieren

 @ApiOperation("导出用户数据")
    @RequestMapping(value = "/export2", method = RequestMethod.GET)
    @ResponseBody
    public void export2(HttpServletResponse response, @RequestParam(value = "keyword", required = false) String keyword,
                       @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
                       @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) throws UnsupportedEncodingException, IOException {
        Page<MesAdmin> adminList = adminService.list(keyword, pageSize, pageNum);

        List<Map<String,String>> list = new ArrayList();
        //因为只有七条数据,所以做了多次循环添加数据
        for(int i=0;i<149795;i++) {
            for (MesAdmin umsAdmin : adminList.getRecords()) {
                Map<String, String> map = new HashMap<>(6);
                DateFormat d1 = DateFormat.getDateInstance();
                map.put("姓名", umsAdmin.getUsername());
                map.put("邮箱", umsAdmin.getEmail());
                map.put("昵称", umsAdmin.getNickName());
                map.put("备注信息", umsAdmin.getNote());
                map.put("创建时间", d1.format( umsAdmin.getCreateTime()));
                String loginTime ="";
                if(umsAdmin.getLoginTime()!=null){
                    loginTime=d1.format( umsAdmin.getLoginTime());
                }
                map.put("最后登录时间",loginTime );
                list.add(map);
            }
        }

        fileUtil.downloadExcelBySXSSF(list,response);
    }

Fazit:

Ich wollte den Export von Daten einführen, fand aber heraus, dass auch der Export von Millionen von Daten eingeführt werden muss. Ich werde morgen den Export von Daten einführen.

Github-Adresse:

Github-Adresse: https://github.com/bangbangzhou/greemes/tree/master

die Öffentlichkeit

SpringBoot kombiniert mit einem POI-Datenbericht auf Millionenebene

Ich denke du magst

Origin blog.51cto.com/15077535/2593725
Empfohlen
Rangfolge