fix:多线程导出

This commit is contained in:
dzc committed 2026-02-04 15:58:13 +08:00
1 parent d25929e461
commit 789d4071e8
3 files changed
+54 -28

No files matched your search

@@ -254,7 +254,7 @@ public class WalletTransactionController {
Long count = walletTransactionMapper.count(dto, dataScope);
if (count > 3 * 10000) throw new RuntimeException("导出数据超出30000条,请缩小查询范围");
walletTransactionService.exportByTemplate(response, dto, "file/个人充值明细.xlsx", dataScope);
walletTransactionService.exportByTemplate(response, dto, count, "file/个人充值明细.xlsx", dataScope);
}
@Operation(summary = "充值统计", description = "充值统计")
@@ -277,7 +277,7 @@ public class WalletTransactionController {
Long count = walletTransactionMapper.count(dto, dataScope);
if (count > 3 * 10000) throw new RuntimeException("导出数据超出30000条,请缩小查询范围");
walletTransactionService.exportByTemplate(response, dto, "file/个人记账扣款明细.xlsx", dataScope);
walletTransactionService.exportByTemplate(response, dto, count, "file/个人记账扣款明细.xlsx", dataScope);
}
@Operation(summary = "记账扣款统计", description = "记账扣款统计")
@@ -300,7 +300,7 @@ public class WalletTransactionController {
Long count = walletTransactionMapper.count(dto, dataScope);
if (count > 3 * 10000) throw new RuntimeException("导出数据超出30000条,请缩小查询范围");
walletTransactionService.exportByTemplate(response, dto, "file/个人消费明细.xlsx", dataScope);
walletTransactionService.exportByTemplate(response, dto, count, "file/个人消费明细.xlsx", dataScope);
}
@Operation(summary = "消费统计", description = "消费统计")
@@ -322,7 +322,7 @@ public class WalletTransactionController {
Long count = walletTransactionMapper.count(dto, dataScope);
if (count > 3 * 10000) throw new RuntimeException("导出数据超出30000条,请缩小查询范围");
walletTransactionService.exportByTemplate(response, dto, "file/个人退款明细.xlsx", dataScope);
walletTransactionService.exportByTemplate(response, dto, count, "file/个人退款明细.xlsx", dataScope);
}
@Operation(summary = "退款统计", description = "退款统计")
@@ -345,7 +345,7 @@ public class WalletTransactionController {
Long count = walletTransactionMapper.count(dto, dataScope);
if (count > 3 * 10000) throw new RuntimeException("导出数据超出30000条,请缩小查询范围");
walletTransactionService.exportByTemplate(response, dto, "file/退还各自食堂明细.xlsx", dataScope);
walletTransactionService.exportByTemplate(response, dto, count, "file/退还各自食堂明细.xlsx", dataScope);
}
@Operation(summary = "退还各自食堂统计", description = "退还各自食堂统计")
@@ -67,7 +67,7 @@ public interface WalletTransactionService extends IService<WalletTransactionEnti
*/
Boolean updateWalletBalance(WalletTransactionDto dto);
void exportByTemplate(HttpServletResponse response, WalletTransactionDto dto, String fileName, DataScope dataScope);
void exportByTemplate(HttpServletResponse response, WalletTransactionDto dto, Long total, String fileName, DataScope dataScope);
/**
* 后台充值统计(导出)
@@ -52,6 +52,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.io.IOException;
import java.math.BigDecimal;
@@ -60,6 +62,9 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
@@ -316,9 +321,9 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
}
@Override
public void exportByTemplate(HttpServletResponse response, WalletTransactionDto dto, String fileName, DataScope dataScope) {
public void exportByTemplate(HttpServletResponse response, WalletTransactionDto dto, Long total, String fileName, DataScope dataScope) {
ExecutorService executor = Executors.newFixedThreadPool(10);
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(ResourceUtil.getStream(fileName)).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
@@ -328,38 +333,59 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
map.put("startTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[1], DatePattern.NORM_DATETIME_PATTERN));
}
long currentPage = 1;
long pageSize = 1000;
long finalTotal = (total == null || total == 0) ? 0 : total;
int pages = (int) ((finalTotal + pageSize - 1) / pageSize);
if (pages == 0) pages = 1;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
List<CompletableFuture<List<WalletTransactionVo>>> futures = new ArrayList<>();
for (int i = 1; i <= pages; i++) {
long currentPage = i;
futures.add(CompletableFuture.supplyAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
Page<WalletTransactionVo> pageList = scopePageList(new Page<>(currentPage, pageSize), dto, dataScope);
if (ObjectUtil.isEmpty(pageList) || ObjectUtil.isEmpty(pageList.getRecords())) {
return new ArrayList<>();
}
List<WalletTransactionVo> list = pageList.getRecords();
for (WalletTransactionVo v : list) {
if (ObjectUtil.isNotEmpty(v.getPrice())) {
v.setPriceStr(BigDecimal.valueOf(v.getPrice()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString());
}
if (ObjectUtil.isNotEmpty(v.getBizType())) {
v.setBizType(WalletBizEnum.valueOfByType(v.getBizType()).getDesc());
}
}
return list;
}, executor));
}
BigDecimal priceTotal = BigDecimal.ZERO;
Long lineNumber = 1L;
// 轮训导出
while (true) {
Page<WalletTransactionVo> pageList = scopePageList(new Page(currentPage, pageSize), dto, dataScope);
if (ObjectUtil.isEmpty(pageList) || ObjectUtil.isEmpty(pageList.getRecords())) break;
List<WalletTransactionVo> list = pageList.getRecords();
// 处理excel start
for (WalletTransactionVo v : list) {
v.setLineNumber(lineNumber);
lineNumber++;
if (ObjectUtil.isNotEmpty(v.getPrice())) {
priceTotal = priceTotal.add(BigDecimal.valueOf(v.getPrice()));
v.setPriceStr(BigDecimal.valueOf(v.getPrice()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString());
}
if (ObjectUtil.isNotEmpty(v.getBizType())) {
v.setBizType(WalletBizEnum.valueOfByType(v.getBizType()).getDesc());
for (CompletableFuture<List<WalletTransactionVo>> future : futures) {
try {
List<WalletTransactionVo> list = future.get();
if (ObjectUtil.isEmpty(list)) continue;
for (WalletTransactionVo v : list) {
v.setLineNumber(lineNumber++);
if (ObjectUtil.isNotEmpty(v.getPrice())) {
priceTotal = priceTotal.add(BigDecimal.valueOf(v.getPrice()));
}
}
excelWriter.fill(list, fillConfig, writeSheet);
} catch (Exception e) {
log.error("|{}|多线程导出获取数据异常", TAG, e);
}
excelWriter.fill(list, fillConfig, writeSheet);
// 处理excel end
if (pageList.getTotal() < pageSize) break;
currentPage++;
}
map.put("computeTotalPayPrice", priceTotal.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString());
excelWriter.fill(map, writeSheet);
} catch (IOException e) {
e.printStackTrace();
log.error("|{}|导入错误,dto:|{}|,fileName:|{}|,error:|{}|", TAG, JSON.toJSONString(dto), fileName, e.getMessage());
} finally {
executor.shutdown();
}
}