项目实战--Spring Boot大数据量报表Excel优化

一、项目场景

项目中要实现交易报表,处理大规模数据导出时,出现单个Excel文件过大导致性能下降的问题,需求是导出大概四千万条数据到Excel文件,不影响正式环境的其他查询。

二、方案
java 复制代码
1.使用读写分离,查询操作由从库处理
2.数据分批查询
3.异步导出数据
4.生成和拆分多个Excel文件
三、实现

1.pom.xml中添加以下依赖:

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- Spring Boot Starter Async -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Apache POI for Excel -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
    </dependency>
</dependencies>

包括SpringBoot、Spring Data JPA、异步处理相关的依赖,以及用于生成Excel文件的Apache POI库。

2.application.properties中加入数据库配置,以及异步任务执行器的配置:

yaml 复制代码
# Database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/yourdatabase
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
# Async configuration
spring.task.execution.pool.core-size=10
spring.task.execution.pool.max-size=20
spring.task.execution.pool.queue-capacity=500
spring.task.execution.thread-name-prefix=Async-thread

3.使用从库进行查询

减轻主库的查询压力,建议在架构上使用读写分离,查询操作由从库处理。这样可以确保主库的操作性能和其他接口查询不受影响。

java 复制代码
@Service
public class DataService {
    @Autowired
    private DataRepository dataRepository;
    public List<Data> fetchData(int offset, int limit) {
        return dataRepository.findAll(PageRequest.of(offset, limit)).getContent();
    }
}

4.数据分批查询策略

防止一次性查询大量数据导致内存溢出,采用分页查询的方式,每次查询部分数据进行处理。

java 复制代码
@Service
public class DataExportService {
    @Autowired
    private DataService dataService;
    @Async
    public void exportData() {
        int pageSize = 10000;
        int pageNumber = 0;
        List<Data> dataBatch;
        do {
            dataBatch = dataService.fetchData(pageNumber, pageSize);
            if (!dataBatch.isEmpty()) {
                // 导出数据到Excel
                exportToExcel(dataBatch, pageNumber);
            }
            pageNumber++;
        } while (!dataBatch.isEmpty());
    }
}

5.异步任务配置

通过@EnableAsync注解启用异步任务,并配置一个任务执行线程来单独执行导出任务。

java 复制代码
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("Async-");
        executor.initialize();
        return executor;
    }
}

6.导出任务接口实现

使用@Async注解将导出任务的方法标记为异步执行。

java 复制代码
@Service
public class DataExportService {
    @Autowired
    private DataService dataService;
    @Async
    public void exportData() {
        // 数据查询和导出的逻辑
    }
}

7.生成和拆分Excel文件

使用Apache POI处理Excel,查询到的数据批次,将数据分成多个Excel文件,避免单个文件过大。

java 复制代码
public void exportToExcel(List<Data> dataBatch, int batchNumber) {
    Workbook workbook = new XSSFWorkbook();
    Sheet sheet = workbook.createSheet("Data");
    int rowNum = 0;
    for (Data data : dataBatch) {
        Row row = sheet.createRow(rowNum++);
        row.createCell(0).setCellValue(data.getId());
        row.createCell(1).setCellValue(data.getName());
        // 其他数据列
    }
    try (FileOutputStream fos = new FileOutputStream("data_batch_" + batchNumber + ".xlsx")) {
        workbook.write(fos);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
相关推荐
千里码aicood13 分钟前
flask基于数字人的储粮知识问答原型系统研究与实现
后端·python·flask
考虑考虑38 分钟前
arthas使用
java·运维·后端
xcl092539 分钟前
从零开发流浪宠物领养平台:技术选型与核心模块设计
java·spring boot·宠物
李昊哲小课1 小时前
Spring Boot 4 旅游主题实战教程 阶段三:数据持久化
spring boot·后端·mybatis·旅游
AI 编程助手GPT1 小时前
Bun 1.4 正式发布:从 Zig 改写为 Rust,内置浏览器、图片处理和并行测试
开发语言·人工智能·后端·ai·chatgpt
wno7041 小时前
Spring-Boot-shiro用户认证
spring boot
IT_陈寒1 小时前
Redis大KEY删除慢到手抖,这几个方法让我少熬一夜
前端·人工智能·后端
paopaokaka_luck1 小时前
基于springboot3+vue3+uniapp的河南非遗数字图谱小程序(协同过滤算法、数字图谱展示、ECharts 图形化分析)
java·前端·spring boot·学习·小程序·uni-app·echarts
步行cgn2 小时前
传统 SSM 与 Spring Boot 开发对比:从配置地狱到约定优于配置
java·spring boot·后端
ms365copilot2 小时前
Excel做完≠结束,Copilot一键生成汇报PPT
powerpoint·excel·copilot