Administrator
06-02 08:39
流式分页导出
/**
* 流式导出方法,用于处理大数据量,避免内存溢出
* @param dataFetcher 数据获取函数,接收页码和页面大小,返回分页结果
* @param fileName 文件名
* @param columns 列定义
* @param response HTTP响应
* @param pageSize 每页大小
*/
public static void exportStream(
BiFunction<Integer, Integer, IPage<?>> dataFetcher,
String fileName,
List<Alias> columns,
HttpServletResponse response,
int pageSize) {
SXSSFWorkbook workbook = null;
try {
// 设置响应头
setResponseHeaders(response, fileName);
// 创建SXSSFWorkbook,设置窗口大小为100行(保留在内存中的行数)
workbook = new SXSSFWorkbook(100);
// 创建工作表
Sheet sheet = workbook.createSheet("数据");
// 创建表头
Row headerRow = sheet.createRow(0);
for (int i = 0; i < columns.size(); i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(columns.get(i).getLabel());
}
// 分批获取数据并写入
int currentPage = 1;
int rowNum = 1; // 从第二行开始写数据(第一行是表头)
while (true) {
// 获取当前页数据
IPage<?> pageResult = dataFetcher.apply(currentPage, pageSize);
List<?> records = pageResult.getRecords();
// 如果没有数据了,退出循环
if (records == null || records.isEmpty()) {
break;
}
// 将数据写入Excel
for (Object record : records) {
Row row = sheet.createRow(rowNum++);
// 根据字段名获取对应的值并写入单元格
for (int col = 0; col < columns.size(); col++) {
String fieldName = columns.get(col).getProp();
Object value = getFieldValue(record, fieldName);
Cell cell = row.createCell(col);
if (value != null) {
cell.setCellValue(value.toString());
} else {
cell.setCellValue("");
}
}
}
// 如果当前页数据少于页面大小,说明已经是最后一页
if (records.size() < pageSize) {
break;
}
currentPage++;
}
// 写入输出流
workbook.write(response.getOutputStream());
} catch (Exception e) {
log.error("流式导出Excel失败", e);
throw new RuntimeException("导出Excel失败", e);
} finally {
if (workbook != null) {
try {
workbook.close();
// 清理临时文件
workbook.dispose();
} catch (Exception e) {
log.warn("关闭Excel工作簿时发生异常", e);
}
}
}
}
/**
* 通过反射获取对象字段值
*/
private static Object getFieldValue(Object obj, String fieldName) {
try {
java.lang.reflect.Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
log.warn("获取字段值失败: " + fieldName, e);
return null;
}
}
0