EasyExcel 支持流式导出,这是它的一个重要特性。流式导出可以有效解决大数据量导出时的内存溢出问题。
流式导出的优势
- 内存友好 :不会一次性将所有数据加载到内存中
- 适合大数据量 :可以处理百万级甚至更多的数据
- 性能稳定 :内存占用相对固定,不会随数据量增长而线性增加
基本用法示例
1. 简单流式导出
@GetMapping("/export")
public void export(HttpServletResponse response) throws IOException {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=data.xlsx");
// 创建ExcelWriter对象
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), DemoData.class).build();
// 分页查询数据并写入
int pageSize = 1000;
int pageNum = 1;
while (true) {
List<DemoData> dataList = getDataFromDatabase(pageNum, pageSize);
if (dataList.isEmpty()) {
break;
}
// 写入当前页数据
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1")
.build();
excelWriter.write(dataList, writeSheet);
pageNum++;
}
// 关闭流
excelWriter.finish();
}
2. 使用分页助手
@GetMapping("/exportWithPage")
public void exportWithPage(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=data.xlsx");
EasyExcel.write(response.getOutputStream(), DemoData.class)
.sheet("Sheet1")
.doWrite(() -> {
// 分页查询数据
List<DemoData> dataList = new ArrayList<>();
int pageSize = 1000;
int pageNum = 1;
while (true) {
List<DemoData> pageData = getDataFromDatabase(pageNum, pageSize);
if (pageData.isEmpty()) {
break;
}
dataList.addAll(pageData);
pageNum++;
}
return dataList;
});
}
3. 手动控制写入过程
@GetMapping("/exportManual")
public void exportManual(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=data.xlsx");
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel.write(response.getOutputStream(), DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 分批写入数据
int pageSize = 1000;
int pageNum = 1;
while (true) {
List<DemoData> dataList = getDataFromDatabase(pageNum, pageSize);
if (dataList.isEmpty()) {
break;
}
excelWriter.write(dataList, writeSheet);
pageNum++;
}
} finally {
if (excelWriter != null) {
excelWriter.finish();
}
}
}
4. 多Sheet流式导出
@GetMapping("/exportMultiSheet")
public void exportMultiSheet(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=data.xlsx");
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), DemoData.class).build();
try {
// 第一个Sheet
WriteSheet sheet1 = EasyExcel.writerSheet(0, "Sheet1").build();
List<DemoData> data1 = getDataForSheet1();
excelWriter.write(data1, sheet1);
// 第二个Sheet
WriteSheet sheet2 = EasyExcel.writerSheet(1, "Sheet2").build();
List<DemoData> data2 = getDataForSheet2();
excelWriter.write(data2, sheet2);
} finally {
excelWriter.finish();
}
}
注意事项
- 及时关闭资源 :使用完后要调用
excelWriter.finish()
关闭流 - 异常处理 :要做好异常处理,确保资源能够正确释放
- 数据分页 :合理设置分页大小,一般建议1000-5000条数据为一批
- 内存监控 :虽然流式导出内存友好,但仍需监控JVM内存使用情况
流式导出是EasyExcel处理大数据量导出的最佳实践,特别适合需要导出大量数据的业务场景。