@RequestMapping("/exportProduct")
public void exportProduct(ProductQueryDTO productQueryDTO,HttpServletRequest request, HttpServletResponse response) throws Exception{
//只有管理員才能導出數據
User user = LoginUtil.getUserInfo();
Integer roleType = user.getRoleType();
if(GlobalConstant.SEVEN != roleType){
return;
}
Set<String> excludeColumnFiledNames = new HashSet<String>(ValidationUtil.getHashMapValue(16));
multiThreadExcelExport.exportExcel("商品", response, productSkuMapper, productQueryDTO, ExportProductDTO.class,excludeColumnFiledNames);
}
/** service
* 導出
* @param name 導出名字
* @param response 導出流
* @param excelMapper 導出的頂級父類
* @param base 查詢的頂級父類
* @param head 導出的實體類
* @throws Exception
*/
@SuppressWarnings("unchecked")
public void exportExcel(String name,HttpServletResponse response,ExcelMapper excelMapper, Base base,Class head, Set<String> excludeColumnFiledNames) throws Exception{
String fileName = name+fastDateFormat.format(new Date());
ExcelWriter writer = EasyExcel.write(getOutputStream(fileName,response),head).excludeColumnFiledNames(excludeColumnFiledNames).registerWriteHandler(myHorizontalCellStyleStrategy()).build();
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").registerWriteHandler(new EasyExcelColumnWidthConfig()).build();
// 根據數據讀寫速度來調整,一般來說讀的邏輯復雜,比較慢,如果讀比寫快,這里設為1
// 查詢總條數
Long count=excelMapper.excelListCount(base);
Long total=count>50000?50000:count;
// 分頁大小可以適當調整
int pageSize = 5000;
Long pageCount = total % pageSize == 0 ? (total / pageSize) : (total / pageSize + 1);
int BlockingQueueSize=pageCount.intValue()==0?1:pageCount.intValue();
// 大小設置為2就可以,作為緩沖
BlockingQueue<List<T>> queue = new ArrayBlockingQueue<>(BlockingQueueSize);
AtomicInteger start = new AtomicInteger(0);
AtomicInteger writerCount = new AtomicInteger(0);
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("excel-pool-%d").build();
//線程池
ExecutorService executorService=new ThreadPoolExecutor(30 , 50 ,
1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(100), threadFactory);
//開啟多個線程分頁查數據
executorService.submit(() -> {
while (start.get()<=total) {
//自增
int pageNum = start.getAndAdd(pageSize);
try {
List<T> list = findPage(pageNum, pageSize,excelMapper,base);
if (CollectionUtils.isEmpty(list)) {
break;
}
queue.put(list);
} catch (Exception e) {
//異常情況也要放入空集合,防止寫線程無法退出循環
log.error("異常情況",e);
}
}
});
Future<?> submit = executorService.submit(() -> {
while (writerCount.get()<total) {
List<T> list = null;
try{
list = queue.take();
writerCount.getAndAdd(list.size());
writer.write(list, writeSheet);
}catch (InterruptedException e){
}
}
try{
writer.finish();
}catch (Exception e) {
log.error("異常情況",e);
System.out.println("6666");
}finally {
executorService.shutdown();
}
});
try {
// 阻塞等待完成,異步處理也可以去掉這段代碼
submit.get();
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
executorService.shutdown();
}
}
private List<T> findPage(int pageNum, int pageSize, ExcelMapper excelMapper,Base base) {
// todo 實現分頁查詢
base.setPage(pageNum);
base.setPageSize(pageSize);
List<T> list=excelMapper.excelList(base);
return list;
}