当前位置: 首页 > news >正文

使用EasyExcel和多线程实现高效数据导出

使用EasyExcel和多线程实现高效数据导出

1. 概述

在企业级应用中,数据导出是一个常见的需求。为了提高导出效率,尤其是在处理大量数据时,我们可以结合使用EasyExcel库和多线程技术。本文将详细介绍如何通过EasyExcel和多线程技术实现高效的数据导出功能。

2. 环境准备

2.1 Java版本

  • Java版本:本项目基于Java开发。

2.2 依赖库

  • com.alibaba:easyexcel: 用于Excel文件的读写操作。
  • org.springframework:spring-jdbc: 提供JDBC模板类,简化数据库操作。

3. 代码结构与逻辑

3.1 类定义

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.*.*.business.core.domain.ExportParam;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

3.2 主要方法解析

3.2.1 exportData

该方法负责设置HTTP响应头,并调用EasyExcel进行Excel文件的生成。同时,它利用多线程分页查询数据,以提升性能。

  public void exportData(ExportParam<?> exportParam, HttpServletResponse response) throws IOException {// 设置响应头response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode(exportParam.getFileName(), "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");// 执行导出try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), exportParam.getEntityClass()).build()) {WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();int total = getTotalCount(exportParam.getSql());int totalPages = (total + exportParam.getPageSize() - 1) / exportParam.getPageSize();ExecutorService executor = Executors.newFixedThreadPool(exportParam.getThreadCount());List<Future<List<?>>> futures = new ArrayList<>();for (int page = 1; page <= totalPages; page++) {int startRow = (page - 1) * exportParam.getPageSize();int endRow = page * exportParam.getPageSize();futures.add(executor.submit(new QueryTask(jdbcTemplate,exportParam.getSql(),exportParam.getEntityClass(),startRow,endRow)));}for (int i = 0; i < totalPages; i++) {List<?> data = futures.get(i).get();excelWriter.write(data, writeSheet);}executor.shutdown();} catch (Exception e) {throw new RuntimeException("导出失败", e);}}
3.2.2 getTotalCount

获取SQL查询结果的总记录数,用于计算分页信息。

private int getTotalCount(String originalSql) {String countSql = "SELECT COUNT(*) FROM (" + originalSql + ")";return jdbcTemplate.queryForObject(countSql, new Object[]{}, Integer.class);}
3.2.3 QueryTask

实现了Callable接口,用于异步执行分页查询任务。

@AllArgsConstructor
private static class QueryTask implements Callable<List<?>> {private final JdbcTemplate jdbcTemplate;private final String originalSql;private final Class<?> entityClass;private final int startRow;private final int endRow;@Overridepublic List<?> call() throws Exception {String paginatedSql = "SELECT * FROM (SELECT ROWNUM rn, temp.* FROM (" + originalSql + ") temp WHERE ROWNUM <= ?) WHERE rn > ?";return jdbcTemplate.query(paginatedSql, new Object[]{endRow, startRow}, new BeanPropertyRowMapper<>(entityClass));}
}

4. 关键点说明

4.1 多线程优化

通过创建固定大小的线程池(ExecutorService),可以并发地执行多个分页查询任务,从而显著减少整体导出时间。每个任务都是一个QueryTask实例,负责从数据库中获取指定范围的数据。

4.2 分页查询

为了避免一次性加载过多数据导致内存溢出,采用了分页查询的方式。每次只查询一页的数据,并将其写入到Excel文件中。

4.3 异常处理

在整个导出过程中,对可能出现的异常进行了捕获和处理,确保即使发生错误也能给出明确提示。

5. 总结

本文介绍了如何使用EasyExcel库结合多线程技术实现高效的数据导出功能。通过合理的分页查询策略和多线程并发执行,不仅提高了导出效率,还保证了系统的稳定性和可靠性。希望这篇文章能够帮助你在实际项目中更好地解决类似问题。


附录

附录A: 依赖管理

pom.xmlbuild.gradle中添加以下依赖:

<!-- pom.xml -->
<dependency> 
<groupId>com.alibaba</groupId> 
<artifactId>easyexcel</artifactId> 
<version>最新版本</version> </dependency> 
<dependency> 
<groupId>org.springframework</groupId> 
<artifactId>spring-jdbc</artifactId> 
<version>最新版本</version> 
</dependency>
// build.gradle 
implementation 'com.alibaba:easyexcel:最新版本' 
implementation 'org.springframework:spring-jdbc:最新版本'

附录B: SQL注意事项

  • 确保SQL查询语句的正确性,特别是分页查询部分。
  • 对于不同数据库,分页语法可能有所不同,请根据实际情况调整。

附录C: 性能调优建议

  • 根据服务器资源情况,合理配置线程池大小。
  • 考虑使用更高效的批量插入方式,如EasyExcel提供的批量写入功能。

希望这份文档对你有所帮助!如果有任何问题或建议,请随时联系我。

相关文章:

使用EasyExcel和多线程实现高效数据导出

​ 使用EasyExcel和多线程实现高效数据导出 1. 概述 在企业级应用中&#xff0c;数据导出是一个常见的需求。为了提高导出效率&#xff0c;尤其是在处理大量数据时&#xff0c;我们可以结合使用EasyExcel库和多线程技术。本文将详细介绍如何通过EasyExcel和多线程技术实现高…...

rabbitmq五种模式的实现——springboot

rabbitmq五种模式的实现——springboot 基础知识和javase的实现形式可以看我之前的博客 代码地址&#xff1a;https://github.com/9lucifer/rabbitmq4j-learning 一、进行集成 &#xff08;一&#xff09;Spring Boot 集成 RabbitMQ 概述 Spring Boot 提供了对 RabbitMQ 的自…...

每日学习Java之一万个为什么

9.Class <?> class1 Myclass.class 为什么要有通配符&#xff1f;传给谁用的&#xff1f; 首先&#xff0c;这里的class特指某个对象在JVM中的元数据集合。 有普通、接口、数组、基本类型、 void 类型、局部类、匿名类、枚举、注解 1.类型安全&#xff1a;通配符允许…...

寒假学习总结

整个寒假都走在数据结构与算法的路上&#xff0c;深入学习了其中多个板块&#xff0c;刷了一些与之对应的题目&#xff0c;下面来一期总结&#xff08;c&#xff09; &#xff08;emmm&#xff0c;主播在寒假试着去学习了几大语言的语法基础&#xff08;丢丢&#xff09; 如Ja…...

Java Web开发实战与项目——用户认证与授权模块开发

Web应用中&#xff0c;用户认证与授权是至关重要的功能&#xff0c;确保只有合法用户才能访问受保护的资源。Spring Security作为一个强大的安全框架&#xff0c;支持多种认证与授权方式。在本章节中&#xff0c;我们将深入探讨三种常见的用户认证与授权方案&#xff1a;基于To…...

力扣每日一题【算法学习day.129】

前言 ###我做这类文章一个重要的目的还是记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&#xff01;&#xff01;&#xff01; 习题 1.数组列表中的最大距离 题目链接…...

uni-app发起网络请求的三种方式

uni.request(OBJECT) 发起网络请求 具体参数可查看官方文档uni-app data:请求的参数; header&#xff1a;设置请求的 header&#xff0c;header 中不能设置 Referer&#xff1b; method&#xff1a;请求方法&#xff1b; timeout&#xff1a;超时时间&#xff0c;单位 ms&a…...

字节火山云DeepSeek接入教程,支持联网,速度超快。

大家好&#xff0c;我是苍何。 在使用 DeepSeek 官网&#xff0c;实在是卡的我差点学猪叫&#xff0c;于是我一直在寻找替代方案。 要求就 2&#xff1a;满血&#xff0c;速度快。&#xff08;当然能联网更好&#xff09;。 我也一度使用了如硅基流动 API&#xff0c;发现也开…...

C语言指针学习笔记

1. 指针的定义 指针&#xff08;Pointer&#xff09;是存储变量地址的变量。在C语言中&#xff0c;指针是一种非常重要的数据类型&#xff0c;通过指针可以直接访问和操作内存。 2. 指针的声明与初始化 2.1 指针声明 指针变量的声明格式为&#xff1a;数据类型 *指针变量名…...

FreeRTOS-rust 编译分析

目录介绍 FreeRTOS-rust ├── .cargo # 对 cargo 本身的配置 │ └── config.toml ├── Cargo.toml # 对当前工作空间的配置 ├── freertos-cargo-build # 负责对 freertos 源码进行编译 │ ├── Cargo.toml # 对当前 package 进行配置 │ └…...

【解决方法】vite-plugin-svg-icons使用中出现问题[vite] Cannot find package ‘fast-glob‘

问题长这样&#xff1a; 参考文章&#xff1a;https://medium.com/wumeng9028/vite-plugin-svg-icons-error-cannot-find-package-fast-glob-8cb03d19c0ac 解决方法&#xff1a;pnpm add fast-glob -D package.json {"vite-plugin-svg-icons": "2.0.1"…...

[Qt] 使用QUndoStack运行到cmd->isObsolete()崩溃

redo/undo中又push了 崩溃情况崩溃原因解决方法 崩溃情况 在正常调用QUndoStack的redo/undo时&#xff0c;崩溃在了这里 unknown:0 QWidget: Cannot create a QWidget without QApplication. 崩溃原因 在正常调用QUndoStack的redo/undo时&#xff0c;因为自身的逻辑处理&a…...

大白话实战Sentinel

Sentinel是SpringCloudAlibaba提供的用来做服务保护的框架,而服务保护的常见手段就是限流和熔断降级。在大型分布式系统里面,由于微服务众多,所以服务之间的稳定性需要做特别关注,Sentinel的核心包就提供了从多个维度去保护服务稳定的策略,而且这些保护策略都可以连接上Se…...

DL/CV领域常见指标术语(FLOPS/mIoU/混淆矩阵/F1-measure)------一篇入门

1. FLOPS、FLOPs和GFLOPs FLOPS: floating-point operations per second&#xff0c;每秒浮点运算次数&#xff0c;用来衡量硬件性能。 FLOPs&#xff1a;floating point of operations&#xff0c;是浮点运算次数&#xff0c;用来衡量算法、模型的复杂度。 GFLOPS&#xff…...

SprutCAMX16数控软件介绍

SprutCAM X 16 是一款功能强大的CAM&#xff08;计算机辅助制造&#xff09;软件&#xff0c;专为数控机床编程和制造过程优化设计。它广泛应用于机械加工、模具制造、3D打印等领域&#xff0c;支持多轴加工、车铣复合、机器人加工等多种加工方式。以下是SprutCAM X 16的主要特…...

Miniconda + VSCode 的Python环境搭建

目录&#xff1a; 安装 VScode 安装 miniconda 在VScode 使用conda虚拟环境 运行Python程序 1.安装 vscode 编辑器 官网链接&#xff1a;Visual Studio Code - Code Editing. Redefined 下载得到&#xff1a;&#xff0c;双击安装。 安装成功…...

TRELLIS 部署笔记

目录 依赖项安装 kaolin安装&#xff1a; 安装和运行报错解决 u2net.onnx 下载 解决方法&#xff0c;就是自行下载&#xff0c;然后拷贝到目录/root/.u2net bash测试u2net&#xff1a; 报错GaussianRasterizationSettings.__new__() got an unexpected keyword argument…...

深入解析Qt事件循环

在Qt开发中&#xff0c;QApplication::exec()这行代码是每个开发者都熟悉的“魔法咒语”。为什么GUI程序必须调用它才能响应操作&#xff1f;为何耗时操作会导致界面冻结&#xff1f;本文将以事件循环为核心&#xff0c;揭示Qt高效运转的底层逻辑&#xff0c;探讨其设计哲学与最…...

Visual Studio Code 集成 Baidu Comate

文章目录 安装Baidu Comate插件 安装Baidu Comate插件 从左主侧栏中 点击 【扩展】这个图标&#xff0c;然后在上方输入栏中输入 baidu comate —>选中列出的Bai Comate —>点击 【安装】按钮&#xff0c;等待安装完毕…...

「正版软件」PDF Reader - 专业 PDF 编辑阅读工具软件

PDF Reader 轻松查看、编辑、批注、转换、数字签名和管理 PDF 文件&#xff0c;以提高工作效率并充分利用 PDF 文档。 像专业人士一样编辑 PDF 编辑 PDF 文本 轻松添加、删除或修改 PDF 文档中的原始文本以更正错误。自定义文本属性&#xff0c;如颜色、字体大小、样式和粗细。…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...