本处理类导出word ,包含12个echart图片和service ,串行执行12*20s=240s (4分钟),采用多线程池执行只需要20秒全部执行完导出word;
DownloadReportController 类:
package com.realize.market.value.controller;
import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.date.DateUtil;
import com.realize.common.core.context.SecurityContextHolder;
import com.realize.common.redis.service.RedisService;
import com.realize.market.value.service.IDownloadReportExecutorService;
import com.realize.market.value.service.IDownloadReportService;
import com.realize.sdk.RemoteBasicService;
import com.realize.sdk.domain.hs.dto.HengShenCompanyInfoDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.*;
@Api(value = "DownloadReportController", description = "下载报告word")
@RestController
@RequestMapping("/downloadReport")
@Slf4j
public class DownloadReportController {
@Autowired
private IDownloadReportService downloadReportService;
@Autowired
private RemoteBasicService remoteBasicService;
@Autowired
private IDownloadReportExecutorService downloadReportExecutorService;
@Autowired
private RedisService redisService;
@Value("F:/plugin")//${phantomjs.root}
private String phantomjsRoot;
private static String DOWNLOADREPORT_WORDDATA="DOWNLOADREPORT:WORDDATA:";
/**
*下载word
* @param response
* @throws Exception
*/
@ApiOperation("下载word")
@PostMapping("/exportToWord")
public void exportToWord(HttpServletResponse response) {
Integer userId = SecurityContextHolder.getUserId();
String secCode = SecurityContextHolder.getUserStockCode();
HengShenCompanyInfoDto companyInfoDto = remoteBasicService.getCompanyInfoByCode(secCode).getData();
String companyReferred = companyInfoDto.getCompanyReferred();
String day = DateUtil.format(new Date(),"yyyyMMdd");
String wordFileName = companyReferred+"("+secCode+")"+"市值诊断报告_"+day+".docx";
try {
//DownloadReportSearchVo downloadReportSearchVo
//downloadReportSearchVo.setSecCode(secCode);
Map<String, Object> wordInitDataMaps = downloadReportExecutorService.exportToWordExecutorService(userId, secCode);
// 前端调用下面初始化word数据方法,下载时候从缓存取word map类型替换数据;
// Map<String, Object> wordInitDataMaps = redisService.getCacheMap(DOWNLOADREPORT_WORDDATA+secCode);
//读取模板 并 一次性提交maps里要替换的文字和图片内容,然后导出word;
/*try {
Thread.sleep(40*1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
XWPFDocument word = null;
try {
word = WordExportUtil.exportWord07(phantomjsRoot+"/MVDR_YYYYMMDD_Template.docx", wordInitDataMaps);
} catch (Exception e) {
e.printStackTrace();
}
response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(wordFileName,"UTF-8"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
ServletOutputStream outputStream = response.getOutputStream();
word.write(outputStream);
outputStream.close();
word.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@ApiOperation("初始化word数据到redis缓存")
@PostMapping("/initWordData")
public void initWordData() {
Integer userId = SecurityContextHolder.getUserId();
String secCode = SecurityContextHolder.getUserStockCode();
Map<String, Object> wordDataMaps = downloadReportExecutorService.exportToWordExecutorService(userId, secCode);
redisService.setCacheMap(DOWNLOADREPORT_WORDDATA+secCode, wordDataMaps);
}
}
-- DownloadReportExecutorServiceImpl 类:
package com.realize.market.value.service.impl;
import cn.hutool.core.map.MapUtil;
import com.realize.market.value.controller.MyEchartDataQueryTaskCallable;
import com.realize.market.value.service.IDownloadReportExecutorService;
import com.realize.market.value.service.IDownloadReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.*;
@Slf4j
@Service
public class DownloadReportExecutorServiceImpl implements IDownloadReportExecutorService {
@Autowired
private IDownloadReportService downloadReportService;
//4大模块,每个模块分配一个线程;
//private static int taskSize=4;
@Override
public Map<String, Object> exportToWordExecutorService(Integer userId, String secCode) {
Map<String, Object> wordInitDataTotalMaps = MapUtil.newHashMap();
// 多线程任务处理;
log.info("下载报告word结束运行开始");
Date dateStart = new Date();
ExecutorService executorService = Executors.newCachedThreadPool();
//CompletionService<String> completionService = new ExecutorCompletionService(executorService);
// 创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for (int i = 0; i < 2; i++) {
MyEchartDataQueryTaskCallable c = new MyEchartDataQueryTaskCallable(i,userId,secCode,downloadReportService);
// 执行任务并获取Future对象
Future f = executorService.submit(c);
// System.out.println(">>>" + f.get().toString());
list.add(f);
}
// 关闭线程池
//pool.shutdown();
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
try {
Map<String, Object> moduleMaps = (Map<String, Object>) f.get();
if(moduleMaps!=null && moduleMaps.size()>0){
wordInitDataTotalMaps.putAll(moduleMaps);
}
log.info("---- DownloadReportExecutorServiceImpl moduleMaps:" + moduleMaps);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Date dateEnd = new Date();
log.info("下载报告word结束运行【" + (dateEnd.getTime() - dateStart.getTime()) + "毫秒】");
return wordInitDataTotalMaps;
}
}
-- 多个任务service MyEchartDataQueryTaskCallable 类:
package com.realize.market.value.controller;
import com.realize.market.value.service.IDownloadReportService;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* 内部多线程任务类-查询所有模块echart 图形数据和文字描述
*/
public class MyEchartDataQueryTaskCallable implements Callable<Map> {
private Integer taskNum;
private Integer userId;
private String secCode;
private IDownloadReportService downloadReportService;
public MyEchartDataQueryTaskCallable(Integer taskNum, Integer userId, String secCode, IDownloadReportService downloadReportService) {
this.taskNum = taskNum;
this.userId = userId;
this.secCode = secCode;
this.downloadReportService = downloadReportService;
}
public Map call() throws Exception {
System.out.println(">>>" + taskNum + "任务启动");
Date dateTmp1 = new Date();
//多线程处理耗时较久的查询各个模块方法;
Map<String, Object> wordInitDataMaps=new HashMap<>();
if(taskNum==0){//1 诊断结果>市值表现,包含3个子模块
wordInitDataMaps = downloadReportService.exportToWord_11(userId,secCode);
}else if(taskNum==1){//2 诊断结果>流动性情况,包含3个子模块
wordInitDataMaps = downloadReportService.exportToWord_12(userId,secCode);
}
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(taskNum + "任务终止"+">>>单个任务耗时:"+time);
return wordInitDataMaps;
}
}
java Executor 线程池并发执行多个耗时任务
于 2023-07-03 13:47:00 首次发布