Browse Source

feat(all): 修改报表模块导出异常问题

master
zhaoqiaobo 9 months ago
parent
commit
4326a36043
  1. 51
      blade-service/logpm-report/src/main/java/com/logpm/report/aspect/AsyncAnnotationAspect.java
  2. 82
      blade-service/logpm-report/src/main/java/com/logpm/report/config/ExecutorConfig.java
  3. 5
      blade-service/logpm-report/src/main/java/com/logpm/report/mapper/ReportDeliverMapeer.java
  4. 13
      blade-service/logpm-report/src/main/java/com/logpm/report/reader/DeliveryDetailReader.java
  5. 16
      blade-service/logpm-report/src/main/java/com/logpm/report/service/IAsyncService.java
  6. 82
      blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/AsyncServiceImpl.java
  7. 5
      blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportBillLoadingAsyncService.java
  8. 9
      blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportDeliverServiceImpl.java
  9. 7
      blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportStockServiceImpl.java
  10. 134
      blade-service/logpm-report/src/main/java/com/logpm/report/util/ReportExcelUtil.java
  11. 4
      blade-service/logpm-report/src/main/java/com/logpm/report/util/ReportUtil.java

51
blade-service/logpm-report/src/main/java/com/logpm/report/aspect/AsyncAnnotationAspect.java

@ -0,0 +1,51 @@
package com.logpm.report.aspect;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springblade.common.annotations.LogpmAsync;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
@Slf4j
@Order(-1)
public class AsyncAnnotationAspect {
/**
* 定义一个切点匹配所有带有@LogpmAsync("asyncExecutor")注解的方法
* 注意实际上Spring Framework自带对@LogpmAsync("asyncExecutor")的处理直接这样配置可能会导致预期之外的行为
*/
@Around("@annotation(org.springblade.common.annotations.LogpmAsync)")
public Object logAroundAsyncMethods(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogpmAsync myAsync = method.getAnnotation(LogpmAsync.class);
String annotationValue = myAsync.value();
log.info(">>>>>>>>>>>>>>>>>> annotationValue={}",annotationValue);
log.info("@LogpmAsync注解的值为asyncExecutor,进行数据源切换 ");
// 在方法执行前的操作
String tenantId = AuthUtil.getTenantId();
log.info(">> tenandId {} ",tenantId);
DynamicDataSourceContextHolder.push(tenantId);
// 执行原方法
Object result = joinPoint.proceed();
// 在方法执行后的操作
DynamicDataSourceContextHolder.poll();
return result;
}
}

82
blade-service/logpm-report/src/main/java/com/logpm/report/config/ExecutorConfig.java

@ -0,0 +1,82 @@
package com.logpm.report.config;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.ThreadLocalUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskDecorator;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@Slf4j
@EnableAsync
public class ExecutorConfig {
@Bean
public Executor asyncExecutor() {
log.info("start async executor");
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
// 配置核心线程数
threadPoolTaskExecutor.setCorePoolSize(10);
// 配置最大线程数
threadPoolTaskExecutor.setMaxPoolSize(20);
// 配置队列大小
threadPoolTaskExecutor.setQueueCapacity(50);
// 配置线程池中线程的名称前缀
threadPoolTaskExecutor.setThreadNamePrefix("ASYNC_THREAD_");
// HelloWorldServiceImpl rejection-policy: 当pool已经达到max size时,如何处理新任务:
// CallerRunsPolicy: 不在新线程中执行任务,而是由调用者所在的线程来执行;
// AbortPolicy: 拒绝执行新任务,并抛出RejectedExecutionException异常;
// DiscardPolicy:丢弃当前将要加入队列的任务;
// DiscardOldestPolicy:丢弃任务队列中最旧的任务;
threadPoolTaskExecutor.setRejectedExecutionHandler(
new ThreadPoolExecutor.CallerRunsPolicy()
);
threadPoolTaskExecutor.setTaskDecorator(new ContextCopyingDecorator());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
static class ContextCopyingDecorator implements TaskDecorator {
@Nonnull
@Override
public Runnable decorate(@Nonnull Runnable runnable) {
RequestAttributes context = RequestContextHolder.currentRequestAttributes();
String tenantId = AuthUtil.getTenantId();
Map<String, Object> all = ThreadLocalUtil.getAll();
Map<String, String> mdcMap = MDC.getCopyOfContextMap();
return () -> {
try {
all.keySet().forEach(key -> ThreadLocalUtil.put(key, all.get(key)));
if (mdcMap != null && !mdcMap.isEmpty()) {
MDC.setContextMap(mdcMap);
}
RequestContextHolder.setRequestAttributes(context);
String tenantId1 = AuthUtil.getTenantId();
runnable.run();
} finally {
RequestContextHolder.resetRequestAttributes();
all.clear();
if (mdcMap != null) {
mdcMap.clear();
}
ThreadLocalUtil.clear();
MDC.clear();
}
};
}
}
}

5
blade-service/logpm-report/src/main/java/com/logpm/report/mapper/ReportDeliverMapeer.java

@ -1,7 +1,6 @@
package com.logpm.report.mapper; package com.logpm.report.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.logpm.report.dto.DeliveryTrainLoadedScanDTO; import com.logpm.report.dto.DeliveryTrainLoadedScanDTO;
@ -63,8 +62,8 @@ public interface ReportDeliverMapeer extends BaseMapper {
* @param queryWrapper * @param queryWrapper
* @return * @return
*/ */
List<ReportDetailVO> getDetailsZeroPage(IPage<ReportDetailVO> page,@Param("ew") QueryWrapper<ReportDetailVO> queryWrapper); List<ReportDetailVO> getDetailsZeroPage(IPage<ReportDetailVO> page,@Param("ew") Wrapper queryWrapper);
Long getDetailsZeroPageCount(@Param("ew") QueryWrapper<ReportDetailVO> queryWrapper); Long getDetailsZeroPageCount(@Param("ew") Wrapper queryWrapper);
List<DeliveryTrainLoadedScanDTO> getDeliveryTrainLoadSacnByIds(@Param("idBatch") List<Long> idBatch); List<DeliveryTrainLoadedScanDTO> getDeliveryTrainLoadSacnByIds(@Param("idBatch") List<Long> idBatch);

13
blade-service/logpm-report/src/main/java/com/logpm/report/reader/DeliveryDetailReader.java

@ -4,14 +4,15 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.logpm.report.mapper.ReportDeliverMapeer; import com.logpm.report.mapper.ReportDeliverMapeer;
import com.logpm.report.service.ExportReader; import com.logpm.report.service.ExportReader;
import io.prometheus.client.CollectorRegistry;
import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
*
* @author zhaoqiaobo * @author zhaoqiaobo
* @create 2024-03-08 9:50 * @create 2024-03-08 9:50
*/ */
@ -20,17 +21,23 @@ public class DeliveryDetailReader implements ExportReader {
@Resource @Resource
private ReportDeliverMapeer reportDeliverMapeer; private ReportDeliverMapeer reportDeliverMapeer;
@Autowired
private CollectorRegistry collectorRegistry;
@Override @Override
public Long getCount(Wrapper query) { public Long getCount(Wrapper query) {
Page page = new Page(1, 1); Page page = new Page(1, 1);
reportDeliverMapeer.getDetailsPage(page, query); reportDeliverMapeer.getDetailsPage(page, query);
return page.getTotal(); Long detailsZeroPageCount = reportDeliverMapeer.getDetailsZeroPageCount(query);
return page.getTotal() + detailsZeroPageCount;
} }
@Override @Override
public List<T> findList(Page page, Wrapper query) { public List<T> findList(Page page, Wrapper query) {
return reportDeliverMapeer.getDetailsPage(page,query); List detailsPage = reportDeliverMapeer.getDetailsPage(page, query);
List detailsZeroPage = reportDeliverMapeer.getDetailsZeroPage(page, query);
detailsPage.addAll(detailsZeroPage);
return detailsPage;
} }
} }

16
blade-service/logpm-report/src/main/java/com/logpm/report/service/IAsyncService.java

@ -0,0 +1,16 @@
package com.logpm.report.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
public interface IAsyncService {
CompletableFuture<List> getListCompletableFuture(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI);
void initExportData(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI, CountDownLatch countDownLatch);
}

82
blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/AsyncServiceImpl.java

@ -0,0 +1,82 @@
package com.logpm.report.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.logpm.report.service.ExportReader;
import com.logpm.report.service.IAsyncService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springblade.common.annotations.LogpmAsync;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@Service
@Slf4j
public class AsyncServiceImpl implements IAsyncService {
@Resource
private Executor asyncExecutor;
@Override
public CompletableFuture<List> getListCompletableFuture(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI) {
CompletableFuture<List> future = CompletableFuture.supplyAsync(() -> {
// 剩余数据
long remaindNum = count - (finalNum * pageSize);
// 当前第几次查询
int current = finalNum + 1;
// 当前查询需要查询几条数据
long lastNum = remaindNum > pageSize ? pageSize : remaindNum;
// 分页查询对象
Page<T> page = new Page(current, lastNum);
// 执行查询操作返回数据
return service.findList(page, query);
}, asyncExecutor);
future.thenAccept(list -> {
if(CollUtil.isNotEmpty(list)){
// 获取组装的数据列表
List<Object> detailVo = pageMap.get(finalI);
// 将查询数据添加到本地缓存
if (CollectionUtil.isEmpty(detailVo)) {
pageMap.put(finalI, list);
} else {
pageMap.get(finalI).addAll(list);
}
}
});
return future;
}
@Override
@LogpmAsync("asyncExecutor")
public void initExportData(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI, CountDownLatch countDownLatch) {
// 剩余数据
long remaindNum = count - (finalNum * pageSize);
// 当前第几次查询
int current = finalNum + 1;
// 当前查询需要查询几条数据
long lastNum = remaindNum > pageSize ? pageSize : remaindNum;
// 分页查询对象
Page<T> page = new Page(current, lastNum);
// 执行查询操作返回数据
List deliveryTrainPage = service.findList(page, query);
// 获取组装的数据列表
List<Object> detailVo = pageMap.get(finalI);
// 将查询数据添加到本地缓存
if (CollectionUtil.isEmpty(detailVo)) {
pageMap.put(finalI, deliveryTrainPage);
} else {
pageMap.get(finalI).addAll(deliveryTrainPage);
}
// 当前线程执行完成
countDownLatch.countDown();
}
}

5
blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportBillLoadingAsyncService.java

@ -52,6 +52,7 @@ public class ReportBillLoadingAsyncService implements IReportBillLoadingAsyncSer
private final BillLoadingTasksReader billLoadingTasksReader; private final BillLoadingTasksReader billLoadingTasksReader;
private final IUserClient userClient; private final IUserClient userClient;
private final IBasicdataWarehouseClient warehouseClient; private final IBasicdataWarehouseClient warehouseClient;
private final ReportExcelUtil reportExcelUtil;
@Override @Override
public IPage<BillLoadingTasksVO> tasksPage(BillLoadingTasksVO vo, BillLoadingTasksQuery query) { public IPage<BillLoadingTasksVO> tasksPage(BillLoadingTasksVO vo, BillLoadingTasksQuery query) {
@ -86,7 +87,7 @@ public class ReportBillLoadingAsyncService implements IReportBillLoadingAsyncSer
tasksCustomQuery(query, queryWrapper); tasksCustomQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, billLoadingTasksReader, BillLoadingTasksVO.class, queryWrapper, "自提任务维度报表"); reportExcelUtil.export(response, billLoadingTasksReader, BillLoadingTasksVO.class, queryWrapper, "自提任务维度报表");
} }
@Override @Override
@ -150,6 +151,6 @@ public class ReportBillLoadingAsyncService implements IReportBillLoadingAsyncSer
detailsCustomQuery(query, queryWrapper); detailsCustomQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, billLoadingDetailsReader, BillLoadingDetailsVO.class, queryWrapper, "自提明细"); reportExcelUtil.export(response, billLoadingDetailsReader, BillLoadingDetailsVO.class, queryWrapper, "自提明细");
} }
} }

9
blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportDeliverServiceImpl.java

@ -52,6 +52,7 @@ public class ReportDeliverServiceImpl implements ReportDeliverService {
private final StockOrderReader stockOrderReader; private final StockOrderReader stockOrderReader;
private final IBasicdataWarehouseClient warehouseClient; private final IBasicdataWarehouseClient warehouseClient;
private final ReportDataService reportDataService; private final ReportDataService reportDataService;
private final ReportExcelUtil reportExcelUtil;
@Override @Override
public IPage<ReportDevilerVO> deliveryTrainPage(ReportDevilerVO vo, ReportDevilerQuery query) { public IPage<ReportDevilerVO> deliveryTrainPage(ReportDevilerVO vo, ReportDevilerQuery query) {
@ -95,7 +96,7 @@ public class ReportDeliverServiceImpl implements ReportDeliverService {
trainCustomQuery(query, queryWrapper); trainCustomQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, deliveryTrainReader, ReportDevilerVO.class, queryWrapper, "配送车次维度报表"); reportExcelUtil.export(response, deliveryTrainReader, ReportDevilerVO.class, queryWrapper, "配送车次维度报表");
} }
@Override @Override
@ -139,7 +140,7 @@ public class ReportDeliverServiceImpl implements ReportDeliverService {
customerCustomQuery(query, queryWrapper); customerCustomQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, deliveryCustomerReader, ReportCustomerVO.class, queryWrapper, "配送客户维度报表"); reportExcelUtil.export(response, deliveryCustomerReader, ReportCustomerVO.class, queryWrapper, "配送客户维度报表");
} }
@Override @Override
@ -204,7 +205,7 @@ public class ReportDeliverServiceImpl implements ReportDeliverService {
detailsCustomQuery(query, queryWrapper); detailsCustomQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, deliveryDetailReader, ReportDetailVO.class, queryWrapper, "配送明细报表"); reportExcelUtil.export(response, deliveryDetailReader, ReportDetailVO.class, queryWrapper, "配送明细报表");
} }
@Override @Override
@ -253,7 +254,7 @@ public class ReportDeliverServiceImpl implements ReportDeliverService {
stockOrderQuery(query, queryWrapper); stockOrderQuery(query, queryWrapper);
// 仓库权限 // 仓库权限
ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouse(), query.getWarehouseRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, stockOrderReader, StockOrderVO.class, queryWrapper, "在库订单表"); reportExcelUtil.export(response, stockOrderReader, StockOrderVO.class, queryWrapper, "在库订单表");
} }
@Override @Override

7
blade-service/logpm-report/src/main/java/com/logpm/report/service/impl/ReportStockServiceImpl.java

@ -44,6 +44,7 @@ public class ReportStockServiceImpl implements ReportStockService {
private final DeliveryOutStocksReader outStocksReader; private final DeliveryOutStocksReader outStocksReader;
private final IDictBizClient dictBizClient; private final IDictBizClient dictBizClient;
private final IBasicdataWarehouseClient warehouseClient; private final IBasicdataWarehouseClient warehouseClient;
private final ReportExcelUtil reportExcelUtil;
@Override @Override
public IPage<StockDetailsVO> detailsPage(StockDetailsVO vo, StockDetailsQuery query) { public IPage<StockDetailsVO> detailsPage(StockDetailsVO vo, StockDetailsQuery query) {
@ -72,7 +73,7 @@ public class ReportStockServiceImpl implements ReportStockService {
QueryWrapper<StockDetailsVO> queryWrapper = QueryUtil.buildQueryWrapper(vo, StockDetailsVO.class); QueryWrapper<StockDetailsVO> queryWrapper = QueryUtil.buildQueryWrapper(vo, StockDetailsVO.class);
detailsCustomQuery(query, queryWrapper); detailsCustomQuery(query, queryWrapper);
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, deliveryStockReader, StockDetailsVO.class, queryWrapper, "库存品表"); reportExcelUtil.export(response, deliveryStockReader, StockDetailsVO.class, queryWrapper, "库存品表");
} }
@Override @Override
@ -123,7 +124,7 @@ public class ReportStockServiceImpl implements ReportStockService {
QueryWrapper<ReportInStockVO> queryWrapper = QueryUtil.buildQueryWrapper(vo, ReportInStockVO.class); QueryWrapper<ReportInStockVO> queryWrapper = QueryUtil.buildQueryWrapper(vo, ReportInStockVO.class);
inStocksCustomQuery(query, queryWrapper); inStocksCustomQuery(query, queryWrapper);
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, inStocksReader, ReportInStockVO.class, queryWrapper, "库存入库表"); reportExcelUtil.export(response, inStocksReader, ReportInStockVO.class, queryWrapper, "库存入库表");
} }
@Override @Override
@ -158,7 +159,7 @@ public class ReportStockServiceImpl implements ReportStockService {
QueryWrapper queryWrapper = QueryUtil.buildQueryWrapper(vo, ReportOutStockVO.class); QueryWrapper queryWrapper = QueryUtil.buildQueryWrapper(vo, ReportOutStockVO.class);
outStocksCustomQuery(query, queryWrapper); outStocksCustomQuery(query, queryWrapper);
ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient); ReportUtil.buildReportWarehouseAuth(vo.getWarehouseName(), query.getWarehouseNameRange(), queryWrapper, warehouseClient);
new ReportExcelUtil().export(response, outStocksReader, ReportOutStockVO.class, queryWrapper, "库存出库表"); reportExcelUtil.export(response, outStocksReader, ReportOutStockVO.class, queryWrapper, "库存出库表");
} }
} }

134
blade-service/logpm-report/src/main/java/com/logpm/report/util/ReportExcelUtil.java

@ -1,5 +1,6 @@
package com.logpm.report.util; package com.logpm.report.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
@ -8,18 +9,27 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.logpm.report.constant.ReportConstants; import com.logpm.report.constant.ReportConstants;
import com.logpm.report.service.ExportReader; import com.logpm.report.service.ExportReader;
import com.logpm.report.service.IAsyncService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.formula.functions.T;
import org.jetbrains.annotations.NotNull;
import org.springblade.core.log.exception.ServiceException; import org.springblade.core.log.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
/** /**
@ -28,6 +38,8 @@ import java.util.concurrent.ExecutorService;
* @author zhaoqiaobo * @author zhaoqiaobo
* @create 2024-03-06 17:48 * @create 2024-03-06 17:48
*/ */
@Slf4j
@Component
public class ReportExcelUtil { public class ReportExcelUtil {
public static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; public static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
@ -41,6 +53,11 @@ public class ReportExcelUtil {
*/ */
public static final Long PAGESIZE = 100000L; public static final Long PAGESIZE = 100000L;
@Resource
private IAsyncService asyncService;
@Autowired
private Executor asyncExecutor;
/** /**
* 设置excel导出的返回头 * 设置excel导出的返回头
* *
@ -88,7 +105,7 @@ public class ReportExcelUtil {
ReportExcelUtil.setExportHeader(response, fileName); ReportExcelUtil.setExportHeader(response, fileName);
// 获取需要导出的总条数 // 获取需要导出的总条数
Long count = service.getCount(query); Long count = service.getCount(query);
if(count > 500000L){ if (count > 500000L) {
throw new ServiceException("导出数据不能大于50w,请增加检索条件"); throw new ServiceException("导出数据不能大于50w,请增加检索条件");
} }
// 每个 sheet 放多少条数据 // 每个 sheet 放多少条数据
@ -98,7 +115,7 @@ public class ReportExcelUtil {
// 总共需要查询数据库几次 // 总共需要查询数据库几次
int findNum = (int) Math.ceil((count / pageSize.doubleValue())); int findNum = (int) Math.ceil((count / pageSize.doubleValue()));
// 封装查询后需要导出的数据 // 封装查询后需要导出的数据
Map<Integer, List<Object>> pageMap = new HashMap<>(ReportConstants.HASHMAP_DEFAULT_SIZE); Map<Integer, List<Object>> pageMap = new ConcurrentHashMap<>(ReportConstants.HASHMAP_DEFAULT_SIZE);
// 定义线程池,大表导出使用一个线程池 // 定义线程池,大表导出使用一个线程池
ExecutorService executorService = ThreadPoolUtil.getThreadPool(); ExecutorService executorService = ThreadPoolUtil.getThreadPool();
// 控制线程全部查询完后执行导出操作 // 控制线程全部查询完后执行导出操作
@ -111,6 +128,7 @@ public class ReportExcelUtil {
e.printStackTrace(); e.printStackTrace();
} }
int num = 0; int num = 0;
List<CompletableFuture<List>> futures = new ArrayList<>();
for (int i = 0; i < sheetNum; i++) { for (int i = 0; i < sheetNum; i++) {
// sheet编号 // sheet编号
int finalI = i + 1; int finalI = i + 1;
@ -123,28 +141,37 @@ public class ReportExcelUtil {
// 查询次数+1 // 查询次数+1
num = num + 1; num = num + 1;
// 提交线程执行查询 // 提交线程执行查询
executorService.submit(() -> { // CompletableFuture<List> future = asyncService.getListCompletableFuture(service, query, pageSize, count, finalNum, pageMap, finalI);
// 剩余数据 // CompletableFuture<List> future = CompletableFuture.supplyAsync(() -> {
long remaindNum = count - (finalNum * pageSize); // // 剩余数据
// 当前第几次查询 // long remaindNum = count - (finalNum * pageSize);
int current = finalNum + 1; // // 当前第几次查询
// 当前查询需要查询几条数据 // int current = finalNum + 1;
long lastNum = remaindNum > pageSize ? pageSize : remaindNum; // // 当前查询需要查询几条数据
// 分页查询对象 // long lastNum = remaindNum > pageSize ? pageSize : remaindNum;
Page<T> page = new Page(current, lastNum); // // 分页查询对象
// 执行查询操作返回数据 // Page<T> page = new Page(current, lastNum);
List deliveryTrainPage = service.findList(page, query); // // 执行查询操作返回数据
// 获取组装的数据列表 // return service.findList(page, query);
List<Object> detailVo = pageMap.get(finalI); // }, asyncExecutor);
// 将查询数据添加到本地缓存 // future.thenAccept(list -> {
if (CollectionUtil.isEmpty(detailVo)) { // if(CollUtil.isNotEmpty(list)){
pageMap.put(finalI, deliveryTrainPage); // // 获取组装的数据列表
} else { // List<Object> detailVo = pageMap.get(finalI);
pageMap.get(finalI).addAll(deliveryTrainPage); // // 将查询数据添加到本地缓存
} // if (CollectionUtil.isEmpty(detailVo)) {
// 当前线程执行完成 // pageMap.put(finalI, list);
countDownLatch.countDown(); // } else {
}); // pageMap.get(finalI).addAll(list);
// }
// }
// });
// futures.add(future);
// asyncExecutor.execute(() -> {
asyncService.initExportData(service, query, pageSize, count, finalNum, pageMap, finalI, countDownLatch);
// });
} }
} }
try { try {
@ -153,6 +180,13 @@ public class ReportExcelUtil {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
// try {
// CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
// allFutures.join();
// } catch (Exception e) {
// log.error("系统异常:{}", e);
// }
// 分sheet向excel中写数据, // 分sheet向excel中写数据,
for (Map.Entry<Integer, List<Object>> entry : pageMap.entrySet()) { for (Map.Entry<Integer, List<Object>> entry : pageMap.entrySet()) {
Integer key = entry.getKey(); Integer key = entry.getKey();
@ -164,4 +198,54 @@ public class ReportExcelUtil {
excelWriter.finish(); excelWriter.finish();
} }
private static void initExportData(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI) {
// 剩余数据
long remaindNum = count - (finalNum * pageSize);
// 当前第几次查询
int current = finalNum + 1;
// 当前查询需要查询几条数据
long lastNum = remaindNum > pageSize ? pageSize : remaindNum;
// 分页查询对象
Page<T> page = new Page(current, lastNum);
// 执行查询操作返回数据
List deliveryTrainPage = service.findList(page, query);
// 获取组装的数据列表
List<Object> detailVo = pageMap.get(finalI);
// 将查询数据添加到本地缓存
if (CollectionUtil.isEmpty(detailVo)) {
pageMap.put(finalI, deliveryTrainPage);
} else {
pageMap.get(finalI).addAll(deliveryTrainPage);
}
}
private static @NotNull CompletableFuture<List> getListCompletableFuture(ExportReader service, Wrapper query, Long pageSize, Long count, int finalNum, Map<Integer, List<Object>> pageMap, int finalI) {
CompletableFuture<List> future = CompletableFuture.supplyAsync(() -> {
// 剩余数据
long remaindNum = count - (finalNum * pageSize);
// 当前第几次查询
int current = finalNum + 1;
// 当前查询需要查询几条数据
long lastNum = remaindNum > pageSize ? pageSize : remaindNum;
// 分页查询对象
Page<T> page = new Page(current, lastNum);
// 执行查询操作返回数据
return service.findList(page, query);
});
future.thenAccept(list -> {
if (CollUtil.isNotEmpty(list)) {
// 获取组装的数据列表
List<Object> detailVo = pageMap.get(finalI);
// 将查询数据添加到本地缓存
if (CollectionUtil.isEmpty(detailVo)) {
pageMap.put(finalI, list);
} else {
pageMap.get(finalI).addAll(list);
}
}
});
return future;
}
} }

4
blade-service/logpm-report/src/main/java/com/logpm/report/util/ReportUtil.java

@ -60,12 +60,14 @@ public class ReportUtil {
} }
public static void dateIsWithinOneMonth(String taskTime, Date startTaskTime, Date endTaskTime, String title) { public static void dateIsWithinOneMonth(String taskTime, Date startTaskTime, Date endTaskTime, String title) {
if (ObjectUtil.isEmpty(taskTime)) { // if (ObjectUtil.isEmpty(taskTime)) {
if (ObjectUtil.isAllNotEmpty(startTaskTime, endTaskTime)) {
boolean withinOneMonth = isWithinOneMonth(startTaskTime, endTaskTime); boolean withinOneMonth = isWithinOneMonth(startTaskTime, endTaskTime);
if (!withinOneMonth) { if (!withinOneMonth) {
throw new ServiceException(title + "必选且时间不超过一个月"); throw new ServiceException(title + "必选且时间不超过一个月");
} }
} }
// }
} }
} }

Loading…
Cancel
Save