Java实现大数据量导出报表
一、实现方式
在Java中,导出数据到Excel有多种方式,每种方式都有其优缺点,适用于不同的场景。以下是常见的几种方式及其特点:
1.1 Apache POI
Apache POI 是 Java 中最流行的库,支持读写 Excel 文件(包括 .xls 和 .xlsx 格式)。
- 特点:
- 支持 .xls(HSSFWorkbook)和 .xlsx(XSSFWorkbook、SXSSFWorkbook)。
- 功能强大,支持样式、公式、图表等。
- SXSSFWorkbook 支持流式写入,适合大数据量导出。
- 适用场景:
- 需要导出复杂格式的 Excel 文件。
- 大数据量导出(使用 SXSSFWorkbook)。
1.2 EasyExcel
EasyExcel 是阿里巴巴开源的 Excel 操作库,基于 Apache POI 封装,专注于大数据量导出和导入。
- 特点:
- 支持流式读写,内存占用低。
- API 简单易用。
- 支持 .xlsx 格式。
- 适用场景:
- 大数据量导出(百万级数据)。
- 需要高性能和低内存占用的场景。
1.3 OpenCSV
虽然不是直接导出 Excel 文件,但 CSV 文件可以被 Excel 直接打开,适合简单的数据导出。
- 特点:
- 轻量级,速度快。
- 文件格式简单,不支持样式、公式等。
- 适合纯数据导出。
- 适用场景:
- 数据量较大,且不需要复杂格式。
- 需要快速导出和导入。
二、使用SXSSFWorkbook
2.1 添加依赖
在pom.xml中添加Apache POI依赖:
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version>
</dependency>
2.2 定义数据模型
创建一个 Java 类表示导出的数据模型。
public class DataModel {private Long id;private String name;private Double value;// 构造方法、Getter 和 Setterpublic DataModel(Long id, String name, Double value) {this.id = id;this.name = name;this.value = value;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getValue() {return value;}public void setValue(Double value) {this.value = value;}
}
2.3 分页查询数据
使用Spring Data JPA或MyBatis进行分页查询。
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;@Service
public class DataService {@Autowiredprivate DataRepository dataRepository;public Page<DataEntity> getDataByPage(int page, int size) {Pageable pageable = PageRequest.of(page, size);return dataRepository.findAll(pageable);}
}
2.4 多线程导出数据
使用线程池并行处理分页查询和数据写入。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.*;@Service
public class ExcelExportService {@Autowiredprivate DataService dataService;// 线程池配置private final ExecutorService executorService = Executors.newFixedThreadPool(10);public void exportLargeDataToExcel(String filePath, int pageSize) throws IOException, InterruptedException, ExecutionException {// 创建 SXSSFWorkbook,设置内存中保留的行数(默认100)try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) {Sheet sheet = workbook.createSheet("Sheet1");// 创建表头Row headerRow = sheet.createRow(0);headerRow.createCell(0).setCellValue("ID");headerRow.createCell(1).setCellValue("Name");headerRow.createCell(2).setCellValue("Value");// 计算总页数long totalCount = dataService.getTotalCount();int totalPages = (int) Math.ceil((double) totalCount / pageSize);// 使用 CountDownLatch 等待所有线程完成CountDownLatch latch = new CountDownLatch(totalPages);// 提交任务到线程池for (int page = 0; page < totalPages; page++) {final int currentPage = page;executorService.submit(() -> {try {// 分页查询数据Page<DataModel> dataPage = dataService.getDataByPage(currentPage, pageSize);List<DataModel> dataList = dataPage.getContent();// 写入当前页数据synchronized (sheet) {int startRow = currentPage * pageSize + 1; // 数据从第2行开始for (int i = 0; i < dataList.size(); i++) {DataModel data = dataList.get(i);Row row = sheet.createRow(startRow + i);row.createCell(0).setCellValue(data.getId());row.createCell(1).setCellValue(data.getName());row.createCell(2).setCellValue(data.getValue());}}} finally {latch.countDown(); // 任务完成}});}// 等待所有线程完成latch.await();// 写入文件try (FileOutputStream outputStream = new FileOutputStream(filePath)) {workbook.write(outputStream);}// 清理临时文件workbook.dispose();}// 关闭线程池executorService.shutdown();}
}
2.5 调用导出方法
在Controller或Service中调用导出方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.concurrent.ExecutionException;@RestController
@RequestMapping("/export")
public class ExportController {@Autowiredprivate ExcelExportService excelExportService;@GetMapping("/excel")public String exportToExcel() throws IOException, InterruptedException, ExecutionException {String filePath = "large_data_export.xlsx";excelExportService.exportLargeDataToExcel(filePath, 10000); // 每页查询10000条数据return "Export successful! File saved at: " + filePath;}
}
三、使用EasyExcel
3.1 添加依赖
在 pom.xml 中添加 EasyExcel 依赖:
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version>
</dependency>
3.2 定义数据模型
创建一个 Java 类表示导出的数据模型。
import com.alibaba.excel.annotation.ExcelProperty;public class DataModel {@ExcelProperty("ID")private Long id;@ExcelProperty("Name")private String name;@ExcelProperty("Value")private Double value;// 构造方法、Getter 和 Setterpublic DataModel(Long id, String name, Double value) {this.id = id;this.name = name;this.value = value;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getValue() {return value;}public void setValue(Double value) {this.value = value;}
}
3.3 分页查询数据
使用 Spring Data JPA 或 MyBatis 进行分页查询。
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;@Service
public class DataService {@Autowiredprivate DataRepository dataRepository;public Page<DataModel> getDataByPage(int page, int size) {Pageable pageable = PageRequest.of(page, size);return dataRepository.findAll(pageable);}
}
3.4 多线程导出数据
使用线程池并行处理分页查询和数据写入。
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.*;@Service
public class ExcelExportService {@Autowiredprivate DataService dataService;// 线程池配置private final ExecutorService executorService = Executors.newFixedThreadPool(10);public void exportLargeDataToExcel(HttpServletResponse response, int pageSize) throws IOException, InterruptedException, ExecutionException {// 设置响应头response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String fileName = "large_data_export.xlsx";response.setHeader("Content-Disposition", "attachment;filename=" + fileName);// 创建 Excel 写入器WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").head(DataModel.class).build();// 计算总页数int totalPages = (int) Math.ceil((double) dataService.getTotalCount() / pageSize);// 使用 CountDownLatch 等待所有线程完成CountDownLatch latch = new CountDownLatch(totalPages);// 提交任务到线程池for (int page = 0; page < totalPages; page++) {final int currentPage = page;executorService.submit(() -> {try {// 分页查询数据Page<DataModel> dataPage = dataService.getDataByPage(currentPage, pageSize);List<DataModel> dataList = dataPage.getContent();// 写入当前页数据EasyExcel.write(response.getOutputStream(), DataModel.class).sheet("Sheet1").doWrite(dataList);} catch (IOException e) {e.printStackTrace();} finally {latch.countDown(); // 任务完成}});}// 等待所有线程完成latch.await();// 关闭线程池executorService.shutdown();}
}
3.5 Controller 调用导出方法
在 Controller 中调用导出方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ExecutionException;@RestController
@RequestMapping("/export")
public class ExportController {@Autowiredprivate ExcelExportService excelExportService;@GetMapping("/excel")public void exportToExcel(HttpServletResponse response) throws IOException, InterruptedException, ExecutionException {excelExportService.exportLargeDataToExcel(response, 10000); // 每页查询10000条数据}
}
四、使用OpenCSV
4.1 添加依赖
在 pom.xml 中添加 OpenCSV 依赖:
<dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>5.8</version>
</dependency>
4.2 定义数据模型
创建一个 Java 类表示导出的数据模型。
public class DataModel {private Long id;private String name;private Double value;// 构造方法、Getter 和 Setterpublic DataModel(Long id, String name, Double value) {this.id = id;this.name = name;this.value = value;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getValue() {return value;}public void setValue(Double value) {this.value = value;}
}
4.3 分页查询数据
使用 Spring Data JPA 或 MyBatis 进行分页查询。
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;@Service
public class DataService {@Autowiredprivate DataRepository dataRepository;public Page<DataModel> getDataByPage(int page, int size) {Pageable pageable = PageRequest.of(page, size);return dataRepository.findAll(pageable);}public long getTotalCount() {return dataRepository.count();}
}
4.4 多线程导出数据
使用线程池并行处理分页查询和数据写入。
import com.opencsv.CSVWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;@Service
public class CsvExportService {@Autowiredprivate DataService dataService;// 线程池配置private final ExecutorService executorService = Executors.newFixedThreadPool(10);public void exportLargeDataToCsv(String filePath, int pageSize) throws IOException, InterruptedException, ExecutionException {// 创建 CSV 写入器try (CSVWriter writer = new CSVWriter(new FileWriter(filePath))) {// 写入表头writer.writeNext(new String[]{"ID", "Name", "Value"});// 计算总页数long totalCount = dataService.getTotalCount();int totalPages = (int) Math.ceil((double) totalCount / pageSize);// 使用 Future 保存每个线程的查询结果List<Future<List<DataModel>>> futures = new ArrayList<>();// 提交任务到线程池for (int page = 0; page < totalPages; page++) {final int currentPage = page;Future<List<DataModel>> future = executorService.submit(() -> {Page<DataModel> dataPage = dataService.getDataByPage(currentPage, pageSize);return dataPage.getContent();});futures.add(future);}// 合并所有线程的查询结果并写入 CSVfor (Future<List<DataModel>> future : futures) {List<DataModel> dataList = future.get();for (DataModel data : dataList) {writer.writeNext(new String[]{String.valueOf(data.getId()),data.getName(),String.valueOf(data.getValue())});}}}// 关闭线程池executorService.shutdown();}
}
4.5 Controller 调用导出方法
在 Controller 中调用导出方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.concurrent.ExecutionException;@RestController
@RequestMapping("/export")
public class ExportController {@Autowiredprivate CsvExportService csvExportService;@GetMapping("/csv")public String exportToCsv() throws IOException, InterruptedException, ExecutionException {String filePath = "large_data_export.csv";csvExportService.exportLargeDataToCsv(filePath, 10000); // 每页查询10000条数据return "Export successful! File saved at: " + filePath;}
}
相关文章:
Java实现大数据量导出报表
一、实现方式 在Java中,导出数据到Excel有多种方式,每种方式都有其优缺点,适用于不同的场景。以下是常见的几种方式及其特点: 1.1 Apache POI Apache POI 是 Java 中最流行的库,支持读写 Excel 文件(包括…...
大语言模型 智能助手——既能生成自然语言回复,又能在必要时调用外部工具获取实时数据
示例代码: import json from langgraph.graph import Graph, END,StateGraph from langchain_core.utils.function_calling import convert_to_openai_function from langchain_community.tools.openweathermap import OpenWeatherMapQueryRun from langchain_core…...
PyTorch 系统教程:理解机器学习数据分割
数据分割是机器学习中的一个基本概念,它直接影响模型的性能和泛化。在本文中,我们将深入研究为什么数据分割在机器学习中很重要,并演示如何使用PyTorch有效地实现它。 理解数据分割 数据分割是将数据集划分为单独的组以进行训练、验证和测试…...
分水岭算法(Watershed Algorithm)教程:硬币分割实例
import cv2 import numpy as np# 1. 图像预处理 img cv2.imread("./water/water_coins.jpeg") gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU) kernel np.ones((3, 3), np.int8)…...
【STM32项目实战系列】基于STM32G474的FDCAN驱动配置
前言:本周工作中用到了CANFD的驱动,由于以前都是用到的CAN2.0,所以过程并不是特别的顺利,所以中间遇到几个比较小的问题导致自己卡住了一段时间,特此记录一下并完全奉上自己的配置的源码。 1,CANFD配置与简…...
shell文本处理
shell文本处理 一、grep 过滤来自一个文件或标准输入匹配模式内容。除了 grep 外,还有 egrep、fgrep。egrep 是 grep 的扩展,相当于 grep -E。fgrep 相当于 grep -f,用的比较少。 用法 grep [OPTION]... PATTERN [FILE]...支持的正则描述…...
如何利用客户端双向TLS认证保护云上应用安全
双向TLS(mTLS)通过要求服务器和客户端双方使用数字证书来验证彼此身份,从而扩展了传统TLS的安全性。常规的TLS只会验证服务器的身份(如大家的浏览器在验证网站时的场景),而mTLS确保在任何数据交换发生之前,双方都对彼此持有信任。在本文中&am…...
nlp第十节——LLM相关
一、模型蒸馏技术 本质上是从一个大模型蒸馏出小模型,从小模型训练出来的概率分布(如自回归模型预测下一个字的概率分布)分别与大模型预测的概率分布和ground label求loss。与大模型预测的概率分布用KL散度求loss,与ground label用…...
T-SQL 语言基础: SQL 数据库对象元数据及配置信息获取
目录 介绍目录视图 获取表和架构名称获取列信息 信息架构视图 获取表信息获取列信息 系统存储过程和函数 获取对象列表获取对象详细信息获取约束信息获取数据库属性信息 总结引用 介绍 在 SQL 数据库管理中,获取数据库对象的元数据信息是至关重要的。元数据提供了…...
ue5 创建多列StreeView的方法与理解
创建StreeView的多列样式怎么就像是创建单行单列差不多?貌似就是在单行单列中加入了多列widget? 示例代码 DetailTabWidget #pragma once #include "TreeViewItemBase.h"class SDetailTabWidget : public SCompoundWidget {SLATE_BEGIN_ARGS(SDetailT…...
C# OnnxRuntime部署DAMO-YOLO香烟检测
目录 说明 效果 模型信息 项目 代码 下载 参考 说明 效果 模型信息 Model Properties ------------------------- --------------------------------------------------------------- Inputs ------------------------- name:input tensor:Floa…...
陕西省地标-DB61/T 1121-2018 政务服务中心建设和运营规范
揭秘陕西省智慧政务服务中心新标准:打造高效便捷的服务新体验 随着信息化时代的深入发展,智慧政务已成为提升政府服务效率、优化营商环境的重要举措。陕西省作为全国政务改革的先行者,近期颁布了《陕西省地标-DB61_T 1121-2018 政务服务中心…...
UDP协议(20250303)
1. UDP UDP:用户数据报协议(User Datagram Protocol),传输层协议之一(UDP,TCP) 2. 特性 发送数据时不需要建立链接,节省资源开销不安全不可靠的协议 //一般用在实时性比较高…...
【四.RAG技术与应用】【12.阿里云百炼应用(下):RAG的云端优化与扩展】
在上一篇文章中,我们聊了如何通过阿里云百炼平台快速搭建一个RAG(检索增强生成)应用,实现文档智能问答、知识库管理等基础能力。今天咱们继续深入,聚焦两个核心问题:如何通过云端技术优化RAG的效果,以及如何扩展RAG的应用边界。文章会穿插实战案例,手把手带你踩坑避雷。…...
Docker新手入门(持续更新中)
一、定义 快速构建、运行、管理应用的工具。 Docker可以帮助我们下载应用镜像,创建并运行镜像的容器,从而快速部署应用。 所谓镜像,就是将应用所需的函数库、依赖、配置等应用一起打包得到的。 所谓容器,为每个镜像的应用进程创建…...
【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架
【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架 1. 引言 本教程旨在帮助嵌入式开发小白从零开始,学习如何在STM32F407微控制器上实现一个基于串口的数据接收程序。该程序能够通过判断数据头来接收一串数据,并将其存储到缓冲区中…...
HSPF 水文模型建模方法与案例分析实践技术应用
在水文模拟领域,HSPF 模型(Hydrological Simulation Program Fortran)与 SWAT 模型一样,都是备受瞩目的水文模型软件。HSPF 模型因其强大的功能和简便的操作,在全球范围内得到了广泛应用。该模型不仅能够在缺乏测量数据…...
设置 CursorRules 规则
为什么要设置CursorRules? 设置 CursorRules 可以帮助优化代码生成和开发流程,提升工作效率。具体的好处包括: 1、自动化代码生成 :通过定义规则,Cursor 可以根据你的开发需求自动生成符合规定的代码模板,…...
人工智能AI在汽车设计领域的应用探索
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活…...
《当AI生成内容遭遇审核:需求与困境的深度剖析》:此文为AI自动生成
AI 内容审核:数字时代的守门人 在当今数字技术迅猛发展的浪潮中,AI 在内容生成领域取得了令人瞩目的成就,成为了推动创新与变革的核心力量。以 AI 绘画为例,从早期简单粗糙的图像生成,到如今能够创作出细节丰富、风格多…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
