欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot+EasyPOI實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)出Excel實(shí)戰(zhàn)指南

 更新時(shí)間:2025年09月18日 09:44:30   作者:寒冰碧海  
這篇文章主要為大家詳細(xì)介紹了一款基于 EasyPOI 和 Apache POI SXSSF 的批量Excel導(dǎo)出工具類 BatchExcelExporter,支持大數(shù)據(jù)量分頁處理,下面小編就來和大家詳細(xì)介紹一下吧

工具簡介

本文介紹一款基于 EasyPOIApache POI SXSSF 的批量Excel導(dǎo)出工具類 BatchExcelExporter,支持大數(shù)據(jù)量分頁處理,避免內(nèi)存溢出(OOM),適合百萬級數(shù)據(jù)導(dǎo)出場景。

環(huán)境準(zhǔn)備

1. 引入Maven依賴

pom.xml 中添加以下依賴(確保使用最新版本):

<!-- EasyPOI 核心庫 -->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

<!-- Apache POI (SXSSF 需要) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>

2. 引入工具類

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

public class BatchExcelExporter<T> {

    private final SXSSFWorkbook workbook;
    private final Class<T> clazz;
    private final List<ExcelExportEntity> exportEntities = new ArrayList<>();
    private int currentRowIndex = 0;

    public BatchExcelExporter(Class<T> clazz) {
        this.clazz = clazz;
        this.workbook = new SXSSFWorkbook(100); // 緩存100行到磁盤
        initHeader();
    }

    // 初始化表頭(僅執(zhí)行一次)
    private void initHeader() {
        // 解析實(shí)體類注解
        List<Field> fields = Arrays.stream(clazz.getDeclaredFields())
                .filter(f -> f.isAnnotationPresent(Excel.class))
                .sorted(Comparator.comparing(f -> {
                    Excel excel = f.getAnnotation(Excel.class);
                    return excel.orderNum();
                })).collect(Collectors.toList());

        // 構(gòu)建導(dǎo)出結(jié)構(gòu)
        fields.forEach(f -> {
            Excel excel = f.getAnnotation(Excel.class);
            exportEntities.add(new ExcelExportEntity(excel.name(), f.getName(), 4000));
        });

        // 創(chuàng)建表頭
        workbook.createSheet("數(shù)據(jù)").createRow(currentRowIndex++);
        addHeaderRow(workbook.getSheetAt(0).getRow(0));
    }

    // 添加表頭行
    private void addHeaderRow(org.apache.poi.ss.usermodel.Row headerRow) {
        for (int i = 0; i < exportEntities.size(); i++) {
            headerRow.createCell(i).setCellValue(exportEntities.get(i).getName());
        }
    }

    // 批量添加數(shù)據(jù)(分頁調(diào)用)
    public void addBatchData(List<T> batchData) throws Exception {
        org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
        for (T data : batchData) {
            org.apache.poi.ss.usermodel.Row row = sheet.createRow(currentRowIndex++);
            fillDataRow(row, data);
        }
        // 每500行刷新到磁盤(根據(jù)數(shù)據(jù)量調(diào)整)
        if (currentRowIndex % 500 == 0) {
            ((SXSSFSheet) sheet).flushRows(500);
        }
    }

    // 填充數(shù)據(jù)行(利用反射動態(tài)取值)
    private void fillDataRow(org.apache.poi.ss.usermodel.Row row, T data) throws Exception {
        for (int i = 0; i < exportEntities.size(); i++) {
            Field field = clazz.getDeclaredField((String) exportEntities.get(i).getKey());
            field.setAccessible(true);
            Object value = field.get(data);
            row.createCell(i).setCellValue(value != null ? value.toString() : "");
        }
    }

    // 最終寫入文件
    public void exportToFile(String filePath) throws Exception {
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            workbook.write(fos);
        } finally {
            workbook.dispose(); // 清理臨時(shí)文件
        }
    }
}

工具類核心功能

動態(tài)表頭生成:通過解析實(shí)體類的 @Excel 注解自動生成表頭。

分頁批量寫入:支持分批次添加數(shù)據(jù),減少內(nèi)存占用。

高性能處理:基于 SXSSFWorkbook,默認(rèn)緩存100行到磁盤。

使用示例

1. 定義實(shí)體類

public class User {
    @Excel(name = "姓名", orderNum = "0")
    private String name;

    @Excel(name = "年齡", orderNum = "1")
    private Integer age;

    @Excel(name = "郵箱", orderNum = "2")
    private String email;

    // 省略Getter/Setter
}

2. 調(diào)用工具類導(dǎo)出數(shù)據(jù)

public class ExcelExportDemo {
    public static void main(String[] args) throws Exception {
        // 初始化導(dǎo)出器(指定實(shí)體類)
        BatchExcelExporter<User> exporter = new BatchExcelExporter<>(User.class);

        // 模擬分頁查詢數(shù)據(jù)(假設(shè)每次查詢1000條)
        for (int page = 1; page <= 10; page++) {
            List<User> batchData = queryUsersByPage(page, 1000);
            exporter.addBatchData(batchData);
        }

        // 導(dǎo)出到文件
        exporter.exportToFile("user_export.xlsx");
    }

    private static List<User> queryUsersByPage(int page, int size) {
        // 模擬數(shù)據(jù)庫查詢(此處返回測試數(shù)據(jù))
        List<User> users = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            users.add(new User("User" + i, 20 + i, "user" + i + "@example.com"));
        }
        return users;
    }
}

關(guān)鍵代碼解析

1.表頭自動生成

通過反射解析實(shí)體類的 @Excel 注解,按 orderNum 排序后生成表頭:

List<Field> fields = Arrays.stream(clazz.getDeclaredFields())
        .filter(f -> f.isAnnotationPresent(Excel.class))
        .sorted(Comparator.comparing(f -> f.getAnnotation(Excel.class).orderNum()))
        .collect(Collectors.toList());

2.數(shù)據(jù)分頁寫入

批量添加數(shù)據(jù)時(shí),每500行刷新到磁盤(避免內(nèi)存堆積):

public void addBatchData(List<T> batchData) throws Exception {
    // ... 填充數(shù)據(jù) ...
    if (currentRowIndex % 500 == 0) {
        ((SXSSFSheet) sheet).flushRows(500);  // ?? 關(guān)鍵性能優(yōu)化點(diǎn)!
    }
}

注意事項(xiàng)

字段類型匹配:確保實(shí)體類字段類型與Excel數(shù)據(jù)兼容(如日期格式需特殊處理)。

性能調(diào)優(yōu):根據(jù)服務(wù)器內(nèi)存調(diào)整 SXSSFWorkbook 的緩存行數(shù)(默認(rèn)100)。

異常處理:建議添加 try-catch 塊捕獲反射和IO異常。

效果展示

導(dǎo)出后的Excel文件示例:

姓名年齡郵箱
User020user0@example.com
User121user1@example.com

擴(kuò)展優(yōu)化方向

  • 樣式自定義:通過 SXSSFCellStyle 設(shè)置單元格樣式(如背景色、邊框)。
  • 多Sheet支持:擴(kuò)展工具類以支持多Sheet動態(tài)切換。
  • 異步導(dǎo)出:結(jié)合線程池實(shí)現(xiàn)異步導(dǎo)出任務(wù)。

到此這篇關(guān)于SpringBoot+EasyPOI實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)出Excel實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)SpringBoot Excel數(shù)據(jù)導(dǎo)出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java IO流操作(PipeInputStream、SequenceInputStream、BufferedInputStream)

    Java IO流操作(PipeInputStream、SequenceInputStream、Buffered

    管道流主要用于線程間通信,分為管道輸入流(PipeInputStream)和管道輸出流(PipeOutputStream),本文介紹了如何通過管道流進(jìn)行數(shù)據(jù)發(fā)送和接收,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-10-10
  • Spring Boot2發(fā)布調(diào)用REST服務(wù)實(shí)現(xiàn)方法

    Spring Boot2發(fā)布調(diào)用REST服務(wù)實(shí)現(xiàn)方法

    這篇文章主要介紹了Spring Boot2發(fā)布調(diào)用REST服務(wù)實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • SpringBoot集成Redis實(shí)現(xiàn)消息隊(duì)列的方法

    SpringBoot集成Redis實(shí)現(xiàn)消息隊(duì)列的方法

    這篇文章主要介紹了SpringBoot集成Redis實(shí)現(xiàn)消息隊(duì)列的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java如何實(shí)現(xiàn)保證線程安全

    Java如何實(shí)現(xiàn)保證線程安全

    這篇文章主要介紹了Java如何實(shí)現(xiàn)保證線程安全問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 解析Jmeter脫離Jenkins后Ant集成郵件通知問題

    解析Jmeter脫離Jenkins后Ant集成郵件通知問題

    今天來講下本地的ant構(gòu)建并發(fā)送郵件。配置下來挺順利也挺簡單的,對Jmeter脫離Jenkins后Ant集成郵件通知問題感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • springboot如何讀取配置文件到靜態(tài)工具類

    springboot如何讀取配置文件到靜態(tài)工具類

    這篇文章主要介紹了springboot實(shí)現(xiàn)讀取配置文件到靜態(tài)工具類方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題

    解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題

    這篇文章主要介紹了解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • mybatis的association傳遞參數(shù)問題示例

    mybatis的association傳遞參數(shù)問題示例

    這篇文章主要介紹了mybatis的association傳遞參數(shù)問題,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • Spring入門基礎(chǔ)之依賴注入

    Spring入門基礎(chǔ)之依賴注入

    Idea中使用@Autowire注解會出現(xiàn)提示黃線,強(qiáng)迫癥患者看著很難受,使用構(gòu)造器注入或者setter方法注入后可解決,下面我們一起來看看
    2022-07-07
  • IDEA中添加xml配置文件時(shí),顯示file問題

    IDEA中添加xml配置文件時(shí),顯示file問題

    這篇文章主要介紹了IDEA中添加xml配置文件時(shí),顯示file問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論