核心原理
通过 EasyPOI 的 exportBigExcel方法实现分页流式导出,避免一次性加载所有数据到内存。
适合百万级数据导出,占用内存恒定,性能稳定。
代码结构
1. 数据查询服务器(核心)
private class DataExportServer implements IExcelExportServer {
private final int PAGE_SIZE = 2000; // 每页条数
@Override
public List<Object> selectListForExcelExport(Object query, int page) {
// 1. 设置分页参数
PageDTO pageQuery = (PageDTO) query;
pageQuery.setPageNum(page);
pageQuery.setPageSize(PAGE_SIZE);
// 2. 查询当前页数据
PageResult<DataVO> pageResult = dataService.getDataByPage(pageQuery);
// 3. 返回数据(空列表表示结束)
return pageResult == null ?
Collections.emptyList() :
new ArrayList<>(pageResult.getList());
}
}
2. 导出接口
@GetMapping("/export")
public void exportData(HttpServletResponse response) throws IOException {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=data.xlsx");
// 创建导出参数
ExportParams params = new ExportParams("报表", "数据");
// 创建查询条件
PageDTO query = new PageDTO();
query.setStartTime("2024-01-01");
query.setEndTime("2024-12-31");
// 执行导出
Workbook workbook = ExcelExportUtil.exportBigExcel(
params,
DataVO.class,
new DataExportServer(),
query
);
// 写入响应流
workbook.write(response.getOutputStream());
workbook.close();
}
执行流程
-
启动导出 :调用
exportBigExcel方法 -
分页查询 :EasyPOI 自动循环调用
DataExportServer.selectListForExcelExport-
第1次:page=1,查询前2000条
-
第2次:page=2,查询2001-4000条
-
直到返回空列表为止
-
-
流式写入:每查询一页,立即写入Excel,不堆积内存
-
完成导出:关闭流,发送给用户
关键优势
-
内存友好:每次只处理一页数据(如2000条)
-
支持海量数据:理论无上限
-
避免OOM:不会一次性加载所有数据
-
自动分页:EasyPOI 控制分页逻辑
注意事项
-
PAGE_SIZE设置:根据数据行宽调整(1000-5000)
-
数据库索引:确保分页查询效率
-
事务管理:长时间查询需注意事务超时
-
资源释放 :必须调用
workbook.close()