一次性读入过多数据,如果内存不够大就会导致内存溢出,所以将数据分批处理,最后在EasyExcel导出的时候再汇总导出。至于接口耗时问题,就需要根据实际调整批次的最大数量。
/**
* 全量导出工艺工时
*
* @param response 请求信息
*/
@Override
public void exportEngineeringStandardWorkTime(HttpServletResponse response) {
//分批获取导出数据
List<List<MoonStandardWorkTimeExportVO>> batchedData = splitIntoBatches();
//导出数据
try {
String fileName = "设备工艺工时信息" + LocalDate.now();
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
EasyExcel.write(response.getOutputStream(), MoonStandardWorkTimeExportVO.class)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new HorizontalCellStyleStrategy(new WriteCellStyle(), contentWriteCellStyle))
.sheet("设备工艺工时信息")
.doWrite(batchedData.stream().flatMap(List::stream).collect(Collectors.toList()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 分批查询
*
* @return 分批后的数据列表
*/
private List<List<MoonStandardWorkTimeExportVO>> splitIntoBatches() {
List<List<MoonStandardWorkTimeExportVO>> batches = new ArrayList<>();
// 分批写入数据
int current = 0;
int batchSize = 100000;
while (true) {
Page page = new Page<>();
current = current + 1;
page.setCurrent(offset);
page.setSize(batchSize);
List<MoonStandardWorkTimeExportVO> batch = this.baseMapper.selectEngineeringStandardWorkTime(page).getRecords();
if (ObjectUtil.isNotEmpty(batch)) {
batches.add(batch);
} else {
break;
}
// 检查内存使用情况,如果内存使用过高,可以考虑定期清理数据
long freeMemory = runtime.freeMemory();
long totalMemory = runtime.totalMemory();
// 如果剩余内存小于总内存的20%
if (freeMemory < totalMemory * 0.2) {
System.gc(); // 请求垃圾回收
runtime.gc(); // 再次请求垃圾回收
}
}
return batches;
}