最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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如何動態(tài)的處理接口的返回?cái)?shù)據(jù)

    java如何動態(tài)的處理接口的返回?cái)?shù)據(jù)

    本文主要介紹了java如何動態(tài)的處理接口的返回?cái)?shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • springbatch使用過程詳解

    springbatch使用過程詳解

    Spring?Batch?是一個功能強(qiáng)大且可擴(kuò)展的批量處理框架,旨在幫助開發(fā)者高效地處理大量數(shù)據(jù)的任務(wù),本文給大家介紹springbatch使用過程詳解,感興趣的朋友一起看看吧
    2025-10-10
  • Java注解@Conditional與@Profile的使用區(qū)別

    Java注解@Conditional與@Profile的使用區(qū)別

    這篇文章主要介紹了Java注解@Conditional與@Profile的使用區(qū)別,@Profile和@Conditional是Spring提供的兩種常用機(jī)制,它們可以根據(jù)不同的條件動態(tài)決定某些Bean是否加載,從而實(shí)現(xiàn)環(huán)境隔離、模塊選擇、特性開關(guān)等功能,需要的朋友可以參考下
    2025-05-05
  • FeignClientFactoryBean創(chuàng)建動態(tài)代理詳細(xì)解讀

    FeignClientFactoryBean創(chuàng)建動態(tài)代理詳細(xì)解讀

    這篇文章主要介紹了FeignClientFactoryBean創(chuàng)建動態(tài)代理詳細(xì)解讀,當(dāng)直接進(jìn)去注冊的方法中,一步步放下走,都是直接放bean的定義信息中放入值,然后轉(zhuǎn)成BeanDefinitionHolder,最后在注冊到IOC容器中,需要的朋友可以參考下
    2023-11-11
  • 解決在IDEA中創(chuàng)建多級package的問題

    解決在IDEA中創(chuàng)建多級package的問題

    這篇文章主要介紹了解決在IDEA中創(chuàng)建多級package的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Maven入門之使用Nexus搭建Maven私服及上傳下載jar包

    Maven入門之使用Nexus搭建Maven私服及上傳下載jar包

    這篇文章主要介紹了Maven入門之使用Nexus搭建Maven私服及上傳下載jar包,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • ibatis學(xué)習(xí)之搭建Java項(xiàng)目

    ibatis學(xué)習(xí)之搭建Java項(xiàng)目

    本文的主要內(nèi)容是簡單介紹了ibatis和如何通過iBatis搭建JAVA項(xiàng)目,包含了一個相關(guān)實(shí)例,需要的朋友可以參考下。
    2017-09-09
  • Java中4種經(jīng)典限流算法講解

    Java中4種經(jīng)典限流算法講解

    本文主要介紹了Java中4種經(jīng)典限流算法講解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • java 判斷字符串是否包含子串的方法

    java 判斷字符串是否包含子串的方法

    這篇文章主要介紹了java 判斷字符串是否包含子串的方法的相關(guān)資料,這里提供了三種方法幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-08-08
  • java實(shí)現(xiàn)科研信息管理系統(tǒng)

    java實(shí)現(xiàn)科研信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java科研信息管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02

最新評論

连平县| 巴林右旗| 赫章县| 阳信县| 屏东县| 霍山县| 黔江区| 梅州市| 江阴市| 五家渠市| 崇州市| 常州市| 安化县| 高雄县| 长武县| 浦县| 临城县| 滕州市| 丹棱县| 南涧| 肃北| 辽宁省| 合肥市| 宁安市| 庆元县| 兴和县| 澳门| 正镶白旗| 镇赉县| 刚察县| 油尖旺区| 肇州县| 鄯善县| 垫江县| 汕尾市| 五大连池市| 乌拉特后旗| 辽中县| 治多县| 北安市| 屯门区|