使用SXSSFWorkbook导出
案例
java
@Override
public void getUserExport(UserExportDTO dto) {
// 开始时间
LocalDateTime time = LocalDateTime.now();
// 准备后续查询需要使用的id集合
List<Integer> userList = testMapper.getUserGetId();
// 创建线程池(根据第二步查询的耗时情况调整大小)
// ExecutorService executor = Executors.newFixedThreadPool(10);
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,// 线程数量
10,// 最大线程数量
1,// 线程存活时间
TimeUnit.MINUTES,// 存活时间单位
// new ArrayBlockingQueue<>(600),// 任务队列
new LinkedBlockingQueue<>(),// 任务队列 -无界队列 (容易内存溢出)
Executors.defaultThreadFactory()// 线程工厂
);
// 使用线程安全的集合存储最终结果
List<UserVO> voList = Collections.synchronizedList(new ArrayList<>());
// 创建任务列表
List<CompletableFuture<Void>> futures = new ArrayList<>();
if (userList != null && userList.size() > 0){
for (Integer id : userList) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 查询用户信息
UserVO userVO = testMapper.getUserFindByIdGetUserVO(id);
// 查询用户详情
List<UserDetails> userDetailsList = testMapper.getUserDetailsByUserId(id);
userVO.setUserDetailsList(userDetailsList);
voList.add(userVO);
}, executor);
// 收集任务
futures.add(future);
}
}
// 等待所有任务完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// 关闭线程池
executor.shutdown();
// 查询结果赋值
List<UserVO> voList2 = voList;
// 处理最终结果排序问题
voList2 = voList2.stream()
.sorted(Comparator.comparing(UserVO::getId))
.collect(Collectors.toList());
// 数据处理完成时间
LocalDateTime time2 = LocalDateTime.now();
// ============================================
try {
// 创建一个新的工作簿
// Workbook workbook = new XSSFWorkbook();
// 创建SXSSFWorkbook,设置行访问窗口为100(内存中保留的行数)
SXSSFWorkbook workbook = new SXSSFWorkbook(500);
// 自动刷新临时文件
workbook.setCompressTempFiles(true);
// 创建一个新的工作表
Sheet sheet = workbook.createSheet("Sheet1");
// 设置标题
Row row = sheet.createRow(0);
String[] headers = {"id","姓名","性别","年龄","电话","地址"};
for (int i = 0; i < headers.length; i++) {
Cell cell = row.createCell(i);
cell.setCellValue(headers[i]);
// 设置列宽
sheet.setColumnWidth(i,30 * 256);
}
// 设置行高
row.setHeightInPoints(30);
// 从第一行开始,第零行是标题
int lineNumber = 1;
// 设置每行数据
for (int i = 0; i < voList2.size(); i++) {
UserVO userVO = voList2.get(i);
List<UserDetails> userDetailsList = userVO.getUserDetailsList();
// id合并
sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,0,0));
// 姓名合并
sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,1,1));
// 性别合并
sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,2,2));
// 年龄
sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,3,3));
// 电话
sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,4,4));
for (UserDetails userDetails : userDetailsList) {
// 创建一行
row = sheet.createRow(lineNumber);
// 设置行高
row.setHeightInPoints(60);
// id
Cell cell = row.createCell(0);
cell.setCellValue(userVO.getId());
// 姓名
cell = row.createCell(1);
cell.setCellValue(userVO.getName());
// 性别
cell = row.createCell(2);
cell.setCellValue(userVO.getSex());
// 年龄
cell = row.createCell(3);
cell.setCellValue(userVO.getAge());
// 电话
cell = row.createCell(4);
cell.setCellValue(userDetails.getTel());
// 地址
cell = row.createCell(5);
cell.setCellValue(userDetails.getAddress());
// 增加一行
lineNumber = lineNumber + 1;
}
}
// 请求头(这两种请求头二选一,具体不同点在于前端下载方式可能不同,二选一即可,可以都试试)
response.setCharacterEncoding("UTF-8");
response.addHeader("content-Type", "application/vnd.ms-excel");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户导出.xlsx", "UTF-8"));
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
// 清理临时文件
workbook.dispose();
//关闭资源
outputStream.flush();
workbook.close();
outputStream.close();
// 数据导出完成时间
LocalDateTime time3 = LocalDateTime.now();
Duration duration = Duration.between(time, time2);
Duration duration2 = Duration.between(time2, time3);
System.out.println("数据处理时间:" + duration.toMillis());
System.out.println("数据导出时间:" + duration2.toMillis());
} catch (IOException e) {
throw new RuntimeException(e);
}
}