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 压缩优化用户体验。这种方案特别适合需要处理大量数据导出的企业系统,在提升效率的同时,保证了系统的稳定性和可扩展性。

相关推荐
非 白8 分钟前
【Java分布式】Nacos注册中心
java·开发语言·nacos·注册中心
吃海鲜的骆驼13 分钟前
服务异步通讯与RabbitMQ
java·分布式·后端·rabbitmq
m0_7482336415 分钟前
RabbitMQ 进阶
android·前端·后端
羱滒17 分钟前
sql调优之数据库开发规范
java·数据库·数据库开发
m0_7482386324 分钟前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
桦说编程26 分钟前
【硬核总结】如何轻松实现只计算一次、惰性求值?良性竞争条件的广泛使用可能超过你的想象!String实际上是可变的?
后端·函数式编程
Forget the Dream1 小时前
设计模式之责任链模式
java·c++·设计模式·责任链模式
jonyleek1 小时前
「JVS更新日志」低代码、企业会议、智能BI、智能排产2.26更新说明
java·大数据·低代码·数据分析·软件需求
计算机小白一个1 小时前
蓝桥杯 Java B 组之最短路径算法(Dijkstra、Floyd-Warshall)
java·数据结构·算法·蓝桥杯
曼岛_1 小时前
[密码学实战]Java实现SM4加解密(ecb,cbc)及工具验证
java·密码学