Spring Boot整合EasyExcel并行导出及Zip压缩下载

1. 项目依赖

首先,我们需要引入相关的依赖,包括 Spring Boot 和阿里巴巴的 EasyExcel 组件,此外还需要使用 Java 的 Zip 工具进行压缩操作。

<dependencies>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- EasyExcel -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>3.0.5</version>
    </dependency>

    <!-- Commons IO(用于压缩文件操作) -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>
2. 创建数据导出逻辑

接下来,我们定义数据导出逻辑。在这个例子中,假设我们有一个订单表,我们将导出每个用户的订单信息到不同的 Excel 文件中。

2.1 定义数据模型
public class Order {
    private Long id;
    private String productName;
    private Integer quantity;
    private BigDecimal price;
    // Getters and Setters
}
2.2 使用 EasyExcel 导出 Excel 文件

EasyExcel 的 API 使用非常简单,下面是一个基本的写 Excel 文件的例子。我们使用 ExcelWriterBuilder 来创建 Excel,并写入数据。

import com.alibaba.excel.EasyExcel;
import java.io.File;
import java.util.List;

public class ExcelExportUtil {

    public static void writeOrdersToExcel(List<Order> orders, String filePath) {
        EasyExcel.write(filePath, Order.class)
                 .sheet("订单数据")
                 .doWrite(orders);
    }
}
2.3 并行导出多个 Excel 文件

为了提高效率,我们可以使用 Java 的 CompletableFuture 实现并行导出。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExportService {

    private final ExecutorService executor = Executors.newFixedThreadPool(10); // 自定义线程池

    public void exportOrdersInParallel(List<List<Order>> ordersList, String outputDir) {
        CompletableFuture[] futures = ordersList.stream()
            .map(orders -> CompletableFuture.runAsync(() -> {
                String fileName = "订单_" + Thread.currentThread().getId() + ".xlsx";
                ExcelExportUtil.writeOrdersToExcel(orders, outputDir + fileName);
            }, executor))
            .toArray(CompletableFuture[]::new);
        
        // 等待所有任务完成
        CompletableFuture.allOf(futures).join();
    }
}

ordersList 是一个包含多个用户订单的列表,每个列表中的订单将导出到一个 Excel 文件。通过使用并行处理,可以同时生成多个文件。

3. 压缩文件为 zip

完成 Excel 文件的导出后,我们需要将这些文件压缩成一个 zip 文件。

3.1 使用 ZipOutputStream 进行压缩
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtil {

    public static void zipFiles(String sourceDir, String zipFile) throws IOException {
        FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        File fileToZip = new File(sourceDir);

        for (File file : fileToZip.listFiles()) {
            FileInputStream fis = new FileInputStream(file);
            ZipEntry zipEntry = new ZipEntry(file.getName());
            zipOut.putNextEntry(zipEntry);

            byte[] bytes = new byte[1024];
            int length;
            while ((length = fis.read(bytes)) >= 0) {
                zipOut.write(bytes, 0, length);
            }
            fis.close();
        }
        zipOut.close();
        fos.close();
    }
}

在这个方法中,我们遍历指定文件夹中的所有文件,并将它们写入到 zip 文件中。

4. 实现下载功能

在 Spring Boot 中,可以通过 HTTP 响应的形式将生成的 zip 文件提供给前端下载。

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;

import java.io.*;

@RestController
public class FileDownloadController {

    @GetMapping("/downloadZip")
    public ResponseEntity<InputStreamResource> downloadZip() throws IOException {
        String zipFilePath = "/tmp/orders.zip";
        ZipUtil.zipFiles("/tmp/excel_files", zipFilePath);

        File file = new File(zipFilePath);
        InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(file.length())
                .body(resource);
    }
}

通过这个接口,前端用户可以通过点击下载链接,直接获取到压缩好的 Excel 文件包。

5. 完整的业务流程
  1. 数据分批处理:假设我们要导出上百万条订单数据,首先需要根据用户或其他条件将数据进行分片,每片数据导出到不同的 Excel 文件。

  2. 并行处理:使用 CompletableFuture 并行处理各个数据片段,确保多个 Excel 文件同时生成,以加快处理速度。

  3. 文件压缩:所有 Excel 文件生成后,通过 ZipOutputStream 将其压缩为一个 zip 文件。

  4. 提供下载:用户通过前端的下载链接,能够方便地获取压缩包。

6. 总结

本文详细介绍了如何使用 Spring BootEasyExcel 实现大规模数据的高效导出,并通过并行处理与 zip 压缩优化用户体验。这种方案特别适合需要处理大量数据导出的企业系统,在提升效率的同时,保证了系统的稳定性和可扩展性。

相关推荐
xiao--xin8 分钟前
Java定时任务实现方案(一)——Timer
java·面试题·八股·定时任务·timer
DevOpsDojo9 分钟前
HTML语言的数据结构
开发语言·后端·golang
MrZhangBaby21 分钟前
SQL-leetcode—1158. 市场分析 I
java·sql·leetcode
一只淡水鱼6635 分钟前
【spring原理】Bean的作用域与生命周期
java·spring boot·spring原理
五味香41 分钟前
Java学习,查找List最大最小值
android·java·开发语言·python·学习·golang·kotlin
时韵瑶1 小时前
Scala语言的云计算
开发语言·后端·golang
jerry-891 小时前
Centos类型服务器等保测评整/etc/pam.d/system-auth
java·前端·github
Jerry Lau1 小时前
大模型-本地化部署调用--基于ollama+openWebUI+springBoot
java·spring boot·后端·llama
小白的一叶扁舟1 小时前
Kafka 入门与应用实战:吞吐量优化与与 RabbitMQ、RocketMQ 的对比
java·spring boot·kafka·rabbitmq·rocketmq
幼儿园老大*1 小时前
【系统架构】如何设计一个秒杀系统?
java·经验分享·后端·微服务·系统架构