@RequestMapping(value = "/img/{procInsId}", method = RequestMethod.GET)
public void img(@PathVariable String procInsId, HttpServletResponse response) {
try {
String picName = "流程图";
// 获取历史流程实例
HistoricProcessInstance historicProcessInstance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(procInsId).singleResult();
// 获取流程中已经执行的节点,按照执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstances = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricActivityInstanceId()
.asc().list();
// 高亮已经执行流程节点ID集合
List<String> highLightedActivitiIds = new ArrayList<>();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
highLightedActivitiIds.add(historicActivityInstance.getActivityId());
}
ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
// 高亮流程已发生流转的线id集合
List<String> highLightedFlowIds = highLightedFlows(bpmnModel, historicActivityInstances);
// 使用默认配置获得流程图表生成器,并生成追踪图片字符流
InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel, "png",
highLightedActivitiIds, highLightedFlowIds, "宋体", "微软雅黑", "黑体", null, 1.0);
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(picName, "UTF-8"));
byte[] b = new byte[1024];
int len = -1;
while ((len = imageStream.read(b, 0, 1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
response.flushBuffer();
} catch (Exception e) {
log.error("[img] ######### 生成流程图失败 ######## 异常:", e);
throw new AudaqueException(e.getMessage());
}
}
/**
* 获取已经流转的线
*
* @param bpmnModel
* @param historicActivityInstances
* @return
*/
public static List<String> highLightedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
// 高亮流程已发生流转的线id集合
List<String> highLightedFlowIds = new ArrayList<>();
// 全部活动节点
List<FlowNode> historicActivityNodes = new ArrayList<>();
// 已完成的历史活动节点
List<HistoricActivityInstance> finishedActivityInstances = new ArrayList<>();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId());
historicActivityNodes.add(flowNode);
if (historicActivityInstance.getEndTime() != null) {
finishedActivityInstances.add(historicActivityInstance);
}
}
FlowNode currentFlowNode = null;
FlowNode targetFlowNode = null;
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
for (HistoricActivityInstance currentActivityInstance : finishedActivityInstances) {
// 获得当前活动对应的节点信息及outgoingFlows信息
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId());
List<SequenceFlow> sequenceFlows = currentFlowNode.getOutgoingFlows();
/**
* 遍历outgoingFlows并找到已已流转的 满足如下条件认为已已流转:
* 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
*/
if ("parallelGateway".equals(currentActivityInstance.getActivityType())
|| "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
// 遍历历史活动节点,找到匹配流程目标节点的
for (SequenceFlow sequenceFlow : sequenceFlows) {
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef());
if (historicActivityNodes.contains(targetFlowNode)) {
highLightedFlowIds.add(targetFlowNode.getId());
}
}
} else {
List<Map<String, Object>> tempMapList = new ArrayList<>();
for (SequenceFlow sequenceFlow : sequenceFlows) {
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
Map<String, Object> map = new HashMap<>(16);
map.put("highLightedFlowId", sequenceFlow.getId());
map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
tempMapList.add(map);
}
}
}
if (!CollectionUtils.isEmpty(tempMapList)) {
// 遍历匹配的集合,取得开始时间最早的一个
long earliestStamp = 0L;
String highLightedFlowId = null;
for (Map<String, Object> map : tempMapList) {
long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
if (earliestStamp == 0 || earliestStamp >= highLightedFlowStartTime) {
highLightedFlowId = map.get("highLightedFlowId").toString();
earliestStamp = highLightedFlowStartTime;
}
}
highLightedFlowIds.add(highLightedFlowId);
}
}
}
return highLightedFlowIds;
}
第二种方式 差不多
/**
* 读取流程资源
*/
@RequestMapping(value = "trace/data/auto/{executionId}")
public void readResource(@PathVariable("executionId") String executionId, HttpServletResponse response)
throws Exception {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstance.getId());
ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
//InputStream imageStream =diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows);
String activityFontName=processEngineConfiguration.getActivityFontName();
String labelFontName=processEngineConfiguration.getLabelFontName();
InputStream imageStream =diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows,activityFontName,labelFontName,null, null, 1.0);
// 输出资源内容到相应对象
response.setContentType("application/octet-stream;charset=UTF-8");
byte[] b = new byte[1024];
int len;
while ((len = imageStream.read(b, 0, 1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
}
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
List<String> highLightedFlows = new ArrayList<String>();
List<HistoricActivityInstance> historicActivityInstances = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime().asc().list();
List<String> historicActivityInstanceList = new ArrayList<String>();
for (HistoricActivityInstance hai : historicActivityInstances) {
historicActivityInstanceList.add(hai.getActivityId());
}
// add current activities to list
List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
historicActivityInstanceList.addAll(highLightedActivities);
// activities and their sequence-flows
for (ActivityImpl activity : processDefinition.getActivities()) {
int index = historicActivityInstanceList.indexOf(activity.getId());
if (index >= 0 && index + 1 < historicActivityInstanceList.size()) {
List<PvmTransition> pvmTransitionList = activity
.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitionList) {
String destinationFlowId = pvmTransition.getDestination().getId();
if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) {
highLightedFlows.add(pvmTransition.getId());
}
}
}
}
return highLightedFlows;
}