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

SpringBoot實(shí)現(xiàn)Excel異步導(dǎo)出的完整實(shí)戰(zhàn)方案

 更新時(shí)間:2025年11月08日 08:45:37   作者:天天摸魚(yú)的java工程師  
在企業(yè)級(jí)后端系統(tǒng)中,Excel導(dǎo)出是一個(gè)幾乎繞不過(guò)去的功能點(diǎn),無(wú)論是報(bào)表系統(tǒng)還是后臺(tái)管理系統(tǒng),下面小編就為大家介紹一個(gè)SpringBoot異步導(dǎo)出Excel的完整實(shí)戰(zhàn)方案吧

8年Java開(kāi)發(fā)經(jīng)驗(yàn)沉淀,獻(xiàn)上一份可以直接落地的異步導(dǎo)出Excel方案。告別“導(dǎo)出慢”“線程卡”“OOM”等老問(wèn)題!

背景

在企業(yè)級(jí)后端系統(tǒng)中,Excel導(dǎo)出是一個(gè)幾乎繞不過(guò)去的功能點(diǎn)。無(wú)論是報(bào)表系統(tǒng)、后臺(tái)管理系統(tǒng),還是BI平臺(tái),用戶都希望“導(dǎo)出一切”。

但真實(shí)場(chǎng)景下,你一定遇到過(guò)這些問(wèn)題:

  • 導(dǎo)出數(shù)據(jù)量大,導(dǎo)出接口超時(shí) 
  • 用戶頻繁導(dǎo)出,線程資源被打爆 
  • 導(dǎo)出阻塞主線程,影響系統(tǒng)性能 
  • 大文件導(dǎo)出,直接OOM 

有沒(méi)有一種 高性能、異步、安全、可控 的導(dǎo)出方案?答案是:有!

目標(biāo)

我們要實(shí)現(xiàn)一個(gè)支持以下特性的 完整異步導(dǎo)出Excel方案

  • 異步任務(wù),不阻塞接口
  • 支持大數(shù)據(jù)量(百萬(wàn)級(jí)別)導(dǎo)出
  • 導(dǎo)出狀態(tài)可查、可取消
  • 文件持久化(本地 / 對(duì)象存儲(chǔ))
  • 支持多種格式(.xlsx、.csv)
  • 任務(wù)失敗原因可追蹤

技術(shù)選型

模塊技術(shù)棧
后端框架Spring Boot
Excel工具EasyExcel
異步支持Spring Async / ThreadPoolTaskExecutor
消息隊(duì)列(可選)RabbitMQ / Kafka
文件存儲(chǔ)本地磁盤(pán) or 阿里OSS / MinIO
狀態(tài)跟蹤Redis / 數(shù)據(jù)庫(kù)
前端交互彈窗 + 輪詢 / WebSocket

架構(gòu)設(shè)計(jì)

text

+-----------+        +-------------+       +-----------+       +----------------+
| 前端請(qǐng)求  | -----> | 導(dǎo)出任務(wù)接口| ---> | 入庫(kù)記錄任務(wù) | --> | 異步任務(wù)執(zhí)行器 |
+-----------+        +-------------+       +-----------+       +--------+-------+
                                                                         |
                                                                 +-------v------+
                                                                 |  Excel導(dǎo)出邏輯 |
                                                                 +-------+------+
                                                                         |
                                                               +---------v---------+
                                                               | 文件存儲(chǔ)(本地/OSS)|
                                                               +---------+---------+
                                                                         |
                                                               +---------v---------+
                                                               | 狀態(tài)更新 & 結(jié)果通知 |
                                                               +-------------------+

核心代碼實(shí)現(xiàn)

1. 定義導(dǎo)出任務(wù)實(shí)體

@Data
@Entity
public class ExportTask {
    @Id
    private String taskId;

    private String fileName;
    private String status; // WAITING, RUNNING, SUCCESS, FAILED
    private String downloadUrl;
    private LocalDateTime createTime;
    private LocalDateTime finishTime;
    private String errorMessage;
}

2. 創(chuàng)建任務(wù)接口(異步提交)

@RestController
@RequestMapping("/export")
public class ExportController {

    @Autowired
    private ExportService exportService;

    @PostMapping("/start")
    public ResponseEntity<String> startExport(@RequestBody ExportRequest request) {
        String taskId = exportService.initExportTask(request);
        return ResponseEntity.ok(taskId);
    }

    @GetMapping("/status/{taskId}")
    public ResponseEntity<ExportTask> getStatus(@PathVariable String taskId) {
        return ResponseEntity.ok(exportService.getExportStatus(taskId));
    }
}

3. 異步導(dǎo)出服務(wù)邏輯

@Service
public class ExportService {

    @Autowired
    private TaskExecutor taskExecutor;

    @Autowired
    private ExportTaskRepository exportTaskRepository;

    public String initExportTask(ExportRequest request) {
        String taskId = UUID.randomUUID().toString();
        ExportTask task = new ExportTask();
        task.setTaskId(taskId);
        task.setStatus("WAITING");
        task.setCreateTime(LocalDateTime.now());
        exportTaskRepository.save(task);

        taskExecutor.execute(() -> doExport(task, request));
        return taskId;
    }

    public void doExport(ExportTask task, ExportRequest request) {
        try {
            task.setStatus("RUNNING");
            exportTaskRepository.save(task);

            String filePath = ExcelExporter.exportToExcel(request); // 核心導(dǎo)出邏輯

            task.setStatus("SUCCESS");
            task.setDownloadUrl(filePath);
        } catch (Exception e) {
            task.setStatus("FAILED");
            task.setErrorMessage(e.getMessage());
        } finally {
            task.setFinishTime(LocalDateTime.now());
            exportTaskRepository.save(task);
        }
    }

    public ExportTask getExportStatus(String taskId) {
        return exportTaskRepository.findById(taskId).orElseThrow();
    }
}

4. Excel導(dǎo)出邏輯(EasyExcel)

public class ExcelExporter {

    public static String exportToExcel(ExportRequest request) throws IOException {
        String filename = "export_" + System.currentTimeMillis() + ".xlsx";
        String filePath = "/data/export/" + filename;

        List<MyData> dataList = fetchData(request); // 分頁(yè)拉取數(shù)據(jù)

        try (OutputStream os = new FileOutputStream(filePath)) {
            ExcelWriter writer = EasyExcel.write(os, MyData.class).build();
            WriteSheet sheet = EasyExcel.writerSheet("Data").build();

            int page = 1;
            while (true) {
                List<MyData> pageData = fetchPageData(page++);
                if (pageData.isEmpty()) break;
                writer.write(pageData, sheet);
            }
            writer.finish();
        }

        return filePath;
    }
}

實(shí)戰(zhàn)Tips & 性能優(yōu)化建議

分頁(yè)拉取數(shù)據(jù)

避免一次性加載全部數(shù)據(jù),使用分頁(yè) + 游標(biāo)方式處理

可結(jié)合 MyBatis RowBounds 或自定義 SQL 分頁(yè)

使用流式寫(xiě)入(Streaming)

EasyExcel 支持流式寫(xiě)入,避免內(nèi)存堆積

避免 List<AllData> 一次性寫(xiě)入

限流 + 防抖機(jī)制

限制用戶導(dǎo)出頻率,避免惡意刷任務(wù)

可使用 Redis 做導(dǎo)出任務(wù)頻率控制

文件清理策略

設(shè)置導(dǎo)出文件過(guò)期時(shí)間,定時(shí)清理

或者上傳到 OSS,減少本地磁盤(pán)壓力

高階玩法(可選)

使用 消息隊(duì)列(MQ) 解耦任務(wù)提交與執(zhí)行

使用 WebSocket 實(shí)時(shí)推送任務(wù)狀態(tài)

使用 MinIO/阿里OSS/七牛云 存儲(chǔ)文件

集成 權(quán)限系統(tǒng),導(dǎo)出內(nèi)容基于用戶角色過(guò)濾

總結(jié)

高性能異步導(dǎo)出Excel,不再是“玄學(xué)”。只要你掌握了以下三點(diǎn):

  • 異步解耦任務(wù)執(zhí)行,不阻塞接口
  • 流式寫(xiě)入 + 分頁(yè)查詢,節(jié)省內(nèi)存
  • 任務(wù)狀態(tài)可查可控,提升用戶體驗(yàn)

這套方案已經(jīng)在多個(gè)企業(yè)項(xiàng)目中落地驗(yàn)證,性能穩(wěn)定,用戶滿意,開(kāi)發(fā)也省心。

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)Excel異步導(dǎo)出的完整實(shí)戰(zhàn)方案的文章就介紹到這了,更多相關(guān)SpringBoot Excel異步導(dǎo)出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java編寫(xiě)簡(jiǎn)單計(jì)算器的完整實(shí)現(xiàn)過(guò)程

    Java編寫(xiě)簡(jiǎn)單計(jì)算器的完整實(shí)現(xiàn)過(guò)程

    這篇文章主要給大家介紹了關(guān)于Java編寫(xiě)簡(jiǎn)單計(jì)算器的完整實(shí)現(xiàn)過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java初學(xué)者了解

    Java初學(xué)者了解"=="與equals的區(qū)別

    這篇文章主要介紹了Java初學(xué)者了解"=="與equals的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • IDEA 開(kāi)發(fā)配置SparkSQL及簡(jiǎn)單使用案例代碼

    IDEA 開(kāi)發(fā)配置SparkSQL及簡(jiǎn)單使用案例代碼

    這篇文章主要介紹了IDEA 開(kāi)發(fā)配置SparkSQL及簡(jiǎn)單使用案例代碼,本文通過(guò)代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • java final本質(zhì)詳解

    java final本質(zhì)詳解

    在本篇文章里小編給大家分享的是關(guān)于java final本質(zhì)的相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考下。
    2019-09-09
  • Java中的FileWriter用法詳解與實(shí)戰(zhàn)記錄

    Java中的FileWriter用法詳解與實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于Java中FileWriter用法的相關(guān)資料,包括寫(xiě)入字符數(shù)據(jù)到文件、字符數(shù)組和部分字符寫(xiě)入、配合BufferedWriter使用等方法,同時(shí)也解釋了其與OutputStreamWriter,BufferedWriter的異同特性,適合簡(jiǎn)單的文件寫(xiě)入操作,需要的朋友可以參考下
    2024-10-10
  • Java實(shí)現(xiàn)兩個(gè)隨機(jī)數(shù)組合并進(jìn)行排序的方法

    Java實(shí)現(xiàn)兩個(gè)隨機(jī)數(shù)組合并進(jìn)行排序的方法

    本文主要介紹了Java實(shí)現(xiàn)兩個(gè)隨機(jī)數(shù)組合并進(jìn)行排序的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Spring Bean初始化的三種常用方式(易懂版)

    Spring Bean初始化的三種常用方式(易懂版)

    在Spring框架開(kāi)發(fā)中,Bean的生命周期管理是核心基礎(chǔ)知識(shí)點(diǎn),而B(niǎo)ean初始化作為生命周期中的關(guān)鍵環(huán)節(jié),負(fù)責(zé)在Bean實(shí)例創(chuàng)建并完成依賴(lài)注入后,執(zhí)行資源加載、參數(shù)配置、緩存初始化等核心業(yè)務(wù)邏輯,本文將詳細(xì)拆解Spring中3種主流的Bean初始化方式,需要的朋友可以參考下
    2025-12-12
  • 手把手教你idea中創(chuàng)建一個(gè)javaweb(webapp)項(xiàng)目詳細(xì)圖文教程

    手把手教你idea中創(chuàng)建一個(gè)javaweb(webapp)項(xiàng)目詳細(xì)圖文教程

    這篇文章主要介紹了如何使用IntelliJ?IDEA創(chuàng)建一個(gè)Maven項(xiàng)目,并配置Tomcat服務(wù)器進(jìn)行運(yùn)行,過(guò)程包括創(chuàng)建項(xiàng)目、配置運(yùn)行環(huán)境、部署項(xiàng)目以及測(cè)試運(yùn)行,需要的朋友可以參考下
    2025-01-01
  • Java中的信號(hào)量Semaphore詳細(xì)解讀

    Java中的信號(hào)量Semaphore詳細(xì)解讀

    這篇文章主要介紹了Java中的信號(hào)量Semaphore詳細(xì)解讀,Java信號(hào)量機(jī)制可以用來(lái)保證線程互斥,創(chuàng)建Semaphore對(duì)象傳入一個(gè)整形參數(shù),類(lèi)似于公共資源,需要的朋友可以參考下
    2023-11-11
  • java算法Leecode刷題統(tǒng)計(jì)有序矩陣中的負(fù)數(shù)

    java算法Leecode刷題統(tǒng)計(jì)有序矩陣中的負(fù)數(shù)

    這篇文章主要為大家介紹了java算法Leecode刷題統(tǒng)計(jì)有序矩陣中的負(fù)數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評(píng)論

杂多县| 开化县| 长阳| 泾川县| 大姚县| 浪卡子县| 高州市| 成安县| SHOW| 永登县| 吉木萨尔县| 皮山县| 金山区| 南城县| 长治市| 曲水县| 寻乌县| 留坝县| 象山县| 兴和县| 安仁县| 灵石县| 富民县| 绥中县| 阳曲县| 舒城县| 德庆县| 汶川县| 咸阳市| 凤城市| 甘南县| 连云港市| 陆丰市| 枝江市| 临沧市| 岑巩县| 拉萨市| 枣强县| 上饶县| 香格里拉县| 车险|