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

SpringBoot整合EasyExcel實(shí)現(xiàn)大規(guī)模數(shù)據(jù)的并行導(dǎo)出與壓縮下載

 更新時(shí)間:2024年10月31日 08:56:58   作者:Yaml墨韻  
在 Spring Boot 應(yīng)用中,整合 EasyExcel 實(shí)現(xiàn)并行導(dǎo)出數(shù)據(jù)并進(jìn)行 Zip 壓縮下載可以極大地提高數(shù)據(jù)處理效率和用戶體驗(yàn),文中通過代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下

一、描述

在 Spring Boot 應(yīng)用中,整合 EasyExcel 實(shí)現(xiàn)并行導(dǎo)出數(shù)據(jù)并進(jìn)行 Zip 壓縮下載可以極大地提高數(shù)據(jù)處理效率和用戶體驗(yàn)。以下是詳細(xì)描述及結(jié)合代碼的示例:

1、EasyExcel 簡介

EasyExcel 是一個(gè) Java 操作 Excel 的開源工具,它能以簡單的方式讀寫大型 Excel 文件,并且性能高效、內(nèi)存占用低。

2、并行導(dǎo)出的優(yōu)勢

在處理大量數(shù)據(jù)導(dǎo)出時(shí),傳統(tǒng)的單線程導(dǎo)出方式可能會非常耗時(shí),導(dǎo)致用戶等待時(shí)間過長。而并行導(dǎo)出可以充分利用多核處理器的優(yōu)勢,將數(shù)據(jù)分成多個(gè)部分同時(shí)進(jìn)行處理,從而大大提高導(dǎo)出速度。

3、Zip 壓縮下載的作用

當(dāng)導(dǎo)出的數(shù)據(jù)量較大時(shí),直接下載可能會導(dǎo)致網(wǎng)絡(luò)傳輸緩慢或者出現(xiàn)問題。通過將導(dǎo)出的 Excel 文件進(jìn)行 Zip 壓縮,可以減小文件大小,提高下載速度,并且方便用戶管理和存儲。

二、案例

1、添加依賴

   <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>easyexcel</artifactId>
       <version>3.1.1</version>
   </dependency>
 
    <!-- 簡化實(shí)體類的get,set操作 --> 
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
 
 
    <!-- Commons IO(用于壓縮文件操作) -->    
    <dependency>        
        <groupId>commons-io</groupId>        
        <artifactId>commons-io</artifactId>        
        <version>2.11.0</version>    
    </dependency>

2、準(zhǔn)備數(shù)據(jù)模型

創(chuàng)建一個(gè)用于存儲數(shù)據(jù)的實(shí)體類:

@Data
public class Order {
    
    private Long id;    
    private String productName;    
    private Integer quantity;    
    private BigDecimal price;    
 
}

3、使用 EasyExcel 導(dǎo)出 Excel 文件

定義了一個(gè)名為ExcelExportUtil 的工具類,其中包含一個(gè)靜態(tài)方法writeToExcel。

這個(gè)方法的主要作用是將一個(gè)訂單列表(List<Order>)中的數(shù)據(jù)寫入到指定路徑的 Excel 文件中。它使用了阿里巴巴的 EasyExcel 庫來實(shí)現(xiàn)這個(gè)功能。

import com.alibaba.excel.EasyExcel;
import java.io.File;
import java.util.List;
 
public class ExcelExportUtil {
    public static void writeToExcel(List<Order> orders, String filePath) {
        try {
            // 使用 EasyExcel 進(jìn)行 Excel 文件寫入操作
            // 指定輸出文件路徑 filePath、數(shù)據(jù)類型 Order.class 和工作表名稱 "訂單數(shù)據(jù)"
            EasyExcel.write(filePath, Order.class)
                   .sheet("訂單數(shù)據(jù)")
                   .doWrite(orders);
        } catch (Exception e) {
            // 如果在寫入過程中出現(xiàn)異常,打印異常信息
            e.printStackTrace();
        }
    }
}

4、實(shí)現(xiàn)并行導(dǎo)出邏輯

import java.util.List;
 
public interface ExportService {
 
    // 并行導(dǎo)出訂單的方法
    void exportOrdersInParallel(List<List<Order>> ordersList, String outputDir);
 
}

實(shí)現(xiàn)ExportService接口,這段代碼實(shí)現(xiàn)了并行導(dǎo)出訂單的功能。它使用了 Java 的CompletableFuture和自定義的線程池來同時(shí)處理多個(gè)訂單列表的導(dǎo)出任務(wù)

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
 
@Service
public class ExportServiceImpl implements ExportService{
 
    // 創(chuàng)建一個(gè)固定大小為 10 的線程池
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
 
    // 并行導(dǎo)出訂單的方法
    public void exportOrdersInParallel(List<List<Order>> ordersList, String outputDir) {
        // 創(chuàng)建一個(gè) CompletableFuture 數(shù)組來存儲每個(gè)任務(wù)的 Future 對象
        CompletableFuture<Void>[] futures = new CompletableFuture[ordersList.size()];
 
        // 遍歷訂單列表,為每個(gè)子列表創(chuàng)建一個(gè)異步任務(wù)
        IntStream.range(0, ordersList.size()).forEach(index -> {
            List<Order> orders = ordersList.get(index);
            futures[index] = CompletableFuture.runAsync(() -> {
                // 生成文件名
                String fileName = "訂單_" + Thread.currentThread().getId() + ".xlsx";
                try {
                    // 調(diào)用工具方法將訂單寫入 Excel 文件
                    ExcelExportUtil.writeOrdersToExcel(orders, outputDir + fileName);
                } catch (Exception e) {
                    // 如果出現(xiàn)異常,打印異常信息
                    e.printStackTrace();
                }
            }, executor);
        });
 
        // 等待所有任務(wù)完成
        CompletableFuture.allOf(futures).join();
    }
}

以下是對代碼的簡單解釋:

  1. 創(chuàng)建一個(gè)固定大小為 10 的線程池Executors,用于執(zhí)行異步任務(wù)。

  2. exportOrdersInParallel方法接受一個(gè)訂單列表和輸出目錄作為參數(shù)。

  3. 創(chuàng)建一個(gè)CompletableFuture<Void>[]數(shù)組來存儲每個(gè)異步任務(wù)的 Future 對象。

  4. 使用IntStream.range遍歷訂單列表的索引,為每個(gè)訂單子列表創(chuàng)建一個(gè)異步任務(wù)。

  5. 在異步任務(wù)中,生成文件名,然后嘗試調(diào)用ExcelExportUtil.writeOrdersToExcel方法將訂單寫入 Excel 文件。如果出現(xiàn)異常,打印異常信息。

  6. 最后,使用CompletableFuture.allOf等待所有異步任務(wù)完成。

請注意,這段代碼假設(shè)存在一個(gè)Order類和一個(gè)ExcelExportUtil工具類,其中包含了將訂單寫入 Excel 文件的方法

5、壓縮文件為 zip

完成 Excel 文件的導(dǎo)出后,我們需要將這些文件壓縮成一個(gè) zip 文件。

5.1 使用 ZipOutputStream

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
 
public class ZipUtil {
    public static void zipFiles(String sourceDir, String zipFile) throws IOException {
        // 創(chuàng)建輸出的 ZIP 文件流
        try (FileOutputStream fos = new FileOutputStream(zipFile);
             ZipOutputStream zipOut = new ZipOutputStream(fos)) {
 
            // 獲取要壓縮的源目錄下的文件列表
            File fileToZip = new File(sourceDir);
            if (fileToZip.isDirectory()) {
                for (File file : fileToZip.listFiles()) {
                    if (file.isFile()) {
                        try (FileInputStream fis = new FileInputStream(file)) {
                            // 創(chuàng)建 ZIP 條目,表示要添加到 ZIP 文件中的文件
                            ZipEntry zipEntry = new ZipEntry(file.getName());
                            zipOut.putNextEntry(zipEntry);
 
                            byte[] bytes = new byte[1024];
                            int length;
                            // 循環(huán)讀取文件內(nèi)容并寫入 ZIP 文件
                            while ((length = fis.read(bytes)) >= 0) {
                                zipOut.write(bytes, 0, length);
                            }
                        }
                    }
                }
            }
        }
    }
}

以下是對代碼的詳細(xì)解釋:

  1. zipFiles方法接受兩個(gè)參數(shù):sourceDir表示要壓縮的源目錄路徑,zipFile表示輸出的 ZIP 文件路徑。

  2. 在方法內(nèi)部,首先創(chuàng)建了一個(gè)FileOutputStream和一個(gè)ZipOutputStream,用于寫入 ZIP 文件。

  3. 然后獲取源目錄下的文件列表。如果源目錄是一個(gè)文件夾,則遍歷其中的文件。

  4. 對于每個(gè)文件,創(chuàng)建一個(gè)FileInputStream來讀取文件內(nèi)容。

  5. 創(chuàng)建一個(gè)ZipEntry,表示要添加到 ZIP 文件中的文件條目,條目名稱為文件的名稱。

  6. 將ZipEntry添加到ZipOutputStream中。

  7. 使用一個(gè)循環(huán),每次讀取 1024 字節(jié)的數(shù)據(jù),并將其寫入到 ZIP 文件中。

  8. 最后,關(guān)閉所有的輸入流和輸出流。

請注意,這段代碼假設(shè)源目錄中只包含文件,不包含子文件夾。如果需要遞歸壓縮子文件夾中的文件,可以對代碼進(jìn)行進(jìn)一步的擴(kuò)展

6. 實(shí)現(xiàn)下載功能

在 Spring Boot 中,可以通過 HTTP 響應(yīng)的形式將生成的 zip 文件提供給前端下載。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class FileDownloadController {
    @GetMapping("/downloadZip")
    public ResponseEntity<InputStreamResource> downloadZip() throws IOException {
        // 定義源目錄路徑,這里假設(shè)是 /tmp/excel_files
        String sourceDir = "/tmp/excel_files";
        // 定義生成的 ZIP 文件路徑,這里假設(shè)是 /tmp/orders.zip
        String zipFilePath = "/tmp/orders.zip";
 
        try {
            // 調(diào)用 ZipUtil 類的方法來壓縮源目錄中的文件到指定的 ZIP 文件
            ZipUtil.zipFiles(sourceDir, zipFilePath);
 
            // 創(chuàng)建一個(gè) File 對象表示要下載的 ZIP 文件
            File file = new File(zipFilePath);
 
            // 創(chuàng)建一個(gè) InputStreamResource 對象,從文件輸入流中讀取數(shù)據(jù)
            InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
 
            // 設(shè)置 HTTP 響應(yīng)頭信息
            HttpHeaders headers = new HttpHeaders();
            // 設(shè)置內(nèi)容處置頭,指示瀏覽器下載文件,并指定文件名
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName());
            // 設(shè)置內(nèi)容類型為 application/octet-stream,表示二進(jìn)制數(shù)據(jù)
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            // 設(shè)置內(nèi)容長度,以便瀏覽器正確顯示下載進(jìn)度
            headers.setContentLength(file.length());
 
            // 返回一個(gè)包含 InputStreamResource 的 ResponseEntity 對象,
            // 表示成功的 HTTP 響應(yīng),包含要下載的文件數(shù)據(jù)和設(shè)置好的響應(yīng)頭
            return ResponseEntity.ok()
                   .headers(headers)
                   .body(resource);
        } catch (IOException e) {
            // 如果在壓縮文件或讀取文件過程中出現(xiàn) IOException,返回內(nèi)部服務(wù)器錯(cuò)誤響應(yīng)
            return ResponseEntity.status(500).build();
        } finally {
            // 在方法結(jié)束時(shí),無論是否發(fā)生異常,嘗試刪除生成的 ZIP 文件
            File zipFile = new File(zipFilePath);
            if (zipFile.exists()) {
                zipFile.delete();
            }
        }
    }
}

7. 完整的業(yè)務(wù)流程

  1. 數(shù)據(jù)分批處理:假設(shè)我們需要導(dǎo)出上百萬條訂單數(shù)據(jù),為了高效管理和處理,首先需要根據(jù)用戶ID、訂單日期或其他相關(guān)條件將龐大的數(shù)據(jù)集進(jìn)行分片。每片數(shù)據(jù)將被獨(dú)立處理并導(dǎo)出到不同的 Excel 文件中,這樣可以有效減少單次處理的數(shù)據(jù)量,避免內(nèi)存溢出等問題。

  2. 并行處理:為了進(jìn)一步提升導(dǎo)出效率,我們可以利用 Java 的 CompletableFuture 框架來并行處理各個(gè)數(shù)據(jù)片段。通過為每個(gè)數(shù)據(jù)片段分配一個(gè)獨(dú)立的導(dǎo)出任務(wù),并讓這些任務(wù)在多個(gè)線程上同時(shí)執(zhí)行,可以確保多個(gè) Excel 文件能夠同時(shí)生成,從而顯著加快整體處理速度。

  3. 文件壓縮:在所有 Excel 文件成功生成后,我們需要將這些文件整合到一個(gè)壓縮包中以便于傳輸和存儲。這時(shí),可以使用 ZipOutputStream 類來創(chuàng)建一個(gè) zip 文件,并將所有生成的 Excel 文件逐一添加到這個(gè) zip 文件中進(jìn)行壓縮。這樣做不僅可以減少文件占用的空間,還能提高文件傳輸?shù)男省?/p>

  4. 提供下載:為了讓用戶能夠方便地獲取壓縮后的數(shù)據(jù)包,我們需要在前端提供一個(gè)下載鏈接。當(dāng)用戶點(diǎn)擊該鏈接時(shí),服務(wù)器會將壓縮包發(fā)送給用戶的瀏覽器進(jìn)行下載。為了確保下載過程的安全性和可靠性,可以采用 HTTPS 協(xié)議進(jìn)行數(shù)據(jù)傳輸,并對下載鏈接進(jìn)行時(shí)效性驗(yàn)證和權(quán)限控制。

三、總結(jié)

本文介紹了使用Spring Boot和EasyExcel實(shí)現(xiàn)大規(guī)模數(shù)據(jù)高效導(dǎo)出的方法,通過數(shù)據(jù)分批處理、并行處理和文件壓縮等技術(shù)手段,提升了導(dǎo)出效率并優(yōu)化了用戶體驗(yàn),特別適用于需要處理大量數(shù)據(jù)的企業(yè)系統(tǒng)。

以上就是SpringBoot整合EasyExcel實(shí)現(xiàn)大規(guī)模數(shù)據(jù)的并行導(dǎo)出與壓縮下載的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot EasyExcel數(shù)據(jù)導(dǎo)出和下載的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決?IDEA?Maven?項(xiàng)目中"Could?not?find?artifact"?問題的常見情況和解決方案

    解決?IDEA?Maven?項(xiàng)目中"Could?not?find?artifact"?

    這篇文章主要介紹了解決IDEA Maven項(xiàng)目中Could not?find?artifact問題的常見情況和解決方案,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • IDEA JarEditor編輯jar包方式(直接新增,修改,刪除jar包內(nèi)的class文件)

    IDEA JarEditor編輯jar包方式(直接新增,修改,刪除jar包內(nèi)的class文件)

    文章主要介紹了如何使用IDEA的JarEditor插件直接修改jar包內(nèi)的class文件,而不需要手動解壓、反編譯和重新打包,通過該插件,可以更方便地進(jìn)行jar包的修改和測試
    2025-01-01
  • Java關(guān)鍵字之this用法詳解

    Java關(guān)鍵字之this用法詳解

    這篇文章將為大家詳細(xì)介紹一下Java關(guān)鍵字this的用法,文中有相關(guān)的代碼示例,希望對大家的學(xué)習(xí)或工作有一定的幫助,感興趣的同學(xué)可以參考下
    2023-05-05
  • 使用Servlet處理一個(gè)上傳的文件

    使用Servlet處理一個(gè)上傳的文件

    今天小編就為大家分享一篇關(guān)于使用Servlet處理一個(gè)上傳的文件,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Spring5新特性之Reactive響應(yīng)式編程

    Spring5新特性之Reactive響應(yīng)式編程

    這篇文章主要介紹了Spring5新特性之Reactive響應(yīng)式編程,響應(yīng)式編程是一種編程范式,通用和專注于數(shù)據(jù)流和變化的,并且是異步的,下文更多詳細(xì)內(nèi)容,需要的小伙伴可以參考一下,希望對你有所幫助
    2022-03-03
  • SpringBoot接收form-data和x-www-form-urlencoded數(shù)據(jù)的方法

    SpringBoot接收form-data和x-www-form-urlencoded數(shù)據(jù)的方法

    form-data和x-www-form-urlencoded是兩種不同的HTTP請求體格式,本文主要介紹了SpringBoot接收form-data和x-www-form-urlencoded數(shù)據(jù)的方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • 記一次公司JVM堆溢出抽絲剝繭定位的過程解析

    記一次公司JVM堆溢出抽絲剝繭定位的過程解析

    這篇文章主要介紹了記一次公司JVM堆溢出抽絲剝繭定位的過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 從dubbo源碼分析qos-server端口沖突問題及解決

    從dubbo源碼分析qos-server端口沖突問題及解決

    這篇文章主要介紹了從dubbo源碼分析qos-server端口沖突問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java IO復(fù)用_動力節(jié)點(diǎn)Java學(xué)院整理

    Java IO復(fù)用_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java IO復(fù)用的相關(guān)知識,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧
    2017-05-05
  • java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解

    java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解

    這篇文章主要介紹了java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解的相關(guān)資料,這里附有實(shí)例代碼,具有參考價(jià)值,需要的朋友可以參考下
    2017-01-01

最新評論