activiti工作流跟踪流程路径出错更正。用了一段时间的activiti,流程监控查看发现线路图跟踪不正确,入下图所示:
解决思路:获取流程经过的所有节点,遍历每个流程发散出去的线,判断哪条线是真实走过的。然后取出高亮线条。亲测无误!
由于安全保密原因不适合展示出多的流程图,确认是哪条线的原理为:A->b A的结束时间等于b的开始时间!!! 来,看代码:
@Controller @RequestMapping(value = "/ViewPorcess") public class ViewPorcessController { @Autowired RepositoryService repositoryService; @Autowired protected RuntimeService runtimeService; @Autowired ProcessEngineConfiguration processEngineConfiguration; @Autowired ProcessEngineFactoryBean processEngine; @Autowired HistoryService historyService; @Autowired TaskService taskService; /** * 读取带跟踪的图片 */ @RequestMapping(value = {"view"}) public void view(HttpServletResponse response, @RequestParam("processInstanceId") String processInstanceId) throws Exception { //获取历史流程实例 HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); //获取流程图 BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); processEngineConfiguration = processEngine.getProcessEngineConfiguration(); Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration); ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator(); ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId()); List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list(); //高亮环节id集合 List<String> highLightedActivitis = new ArrayList<String>(); // //高亮线路id集合 List<String> highLightedFlows = getHighLightedFlows(definitionEntity,highLightedActivitList); //当前流程实例执行到哪个节点 ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();// 执行实例 if(execution!=null){ highLightedActivitis.add(execution.getActivityId()); } //中文显示的是口口口,设置字体就好了 InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis,highLightedFlows,"宋体","宋体","宋体",null,1.0); //单独返回流程图,不高亮显示 // InputStream imageStream = diagramGenerator.generatePngDiagram(bpmnModel); // 输出资源内容到相应对象 byte[] b = new byte[1024]; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int len; while ((len = imageStream.read(b, 0, 1024)) != -1) { //response.getOutputStream().write(b, 0, len); byteArrayOutputStream.write(b, 0, len); } String flowImgBase64 = new String(Base64.encodeBase64(byteArrayOutputStream.toByteArray()),"UTF-8"); response.getWriter().print(flowImgBase64); response.getWriter().flush(); } /** * 获取需要高亮的线 * @param processDefinitionEntity * @param historicActivityInstances * @return */ private List<String> getHighLightedFlows( ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) { List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId List<ViewProcessSameStartTimeNode> sameStartTimeNodes = new ArrayList<ViewProcessSameStartTimeNode>(); for(int i = 0; i < historicActivityInstances.size(); i++){ ActivityImpl activityImpl = processDefinitionEntity .findActivity(historicActivityInstances.get(i) .getActivityId()); if(StringUtils.isEmpty(historicActivityInstances.get(i).getActivityName())==true || "exclusiveGateway".equals(historicActivityInstances.get(i).getActivityType()) == true){ for(int j=0;j<i;j++){ long t1 = historicActivityInstances.get(i).getEndTime().getTime()/1000; long t2 = historicActivityInstances.get(j).getStartTime().getTime()/1000; if(t1 == t2){ ViewProcessSameStartTimeNode viewProcessSameStartTimeNode = new ViewProcessSameStartTimeNode(); viewProcessSameStartTimeNode.setSourceNode(processDefinitionEntity .findActivity(historicActivityInstances.get(i) .getActivityId())); viewProcessSameStartTimeNode.setDestinationNode(processDefinitionEntity .findActivity(historicActivityInstances.get(j) .getActivityId())); sameStartTimeNodes.add(viewProcessSameStartTimeNode); } } for(int j=i+1;j<historicActivityInstances.size();j++){ long t1 = historicActivityInstances.get(i).getEndTime().getTime()/1000; long t2 = historicActivityInstances.get(j).getStartTime().getTime()/1000; if(t1 == t2){ ViewProcessSameStartTimeNode viewProcessSameStartTimeNode = new ViewProcessSameStartTimeNode(); viewProcessSameStartTimeNode.setSourceNode(processDefinitionEntity .findActivity(historicActivityInstances.get(i) .getActivityId())); viewProcessSameStartTimeNode.setDestinationNode(processDefinitionEntity .findActivity(historicActivityInstances.get(j) .getActivityId())); sameStartTimeNodes.add(viewProcessSameStartTimeNode); } } continue; } //最后一个节点不要后续线条 if(historicActivityInstances.get(i).getEndTime()==null){ continue; } List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();// 取出节点的所有出去的线 for (PvmTransition pvmTransition : pvmTransitions) { // 对所有的线进行遍历 ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition .getDestination(); if(StringUtils.isEmpty(historicActivityInstances.get(i).getActivityName())==true || "exclusiveGateway".equals(historicActivityInstances.get(i).getActivityType()) == true){ }else{ highFlows.add(pvmTransition.getId()); } } } for(int i = 0; i < historicActivityInstances.size(); i++){ ActivityImpl activityImpl = processDefinitionEntity .findActivity(historicActivityInstances.get(i) .getActivityId()); List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();// 取出节点的所有出去的线 for (PvmTransition pvmTransition : pvmTransitions) { // 对所有的线进行遍历 ActivityImpl pvmActivityImplSource = (ActivityImpl) pvmTransition .getSource(); ActivityImpl pvmActivityImplDestination = (ActivityImpl) pvmTransition .getDestination(); // 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示 for(ViewProcessSameStartTimeNode v:sameStartTimeNodes){ if(v.getSourceNode()== pvmActivityImplSource && v.getDestinationNode() == pvmActivityImplDestination){ highFlows.add(pvmTransition.getId()); } } } } return highFlows; } }
其实涉及到一个自定义类:
public class ViewProcessSameStartTimeNode { private ActivityImpl sourceNode; private ActivityImpl destinationNode; public ActivityImpl getSourceNode() { return sourceNode; } public void setSourceNode(ActivityImpl sourceNode) { this.sourceNode = sourceNode; } public ActivityImpl getDestinationNode() { return destinationNode; } public void setDestinationNode(ActivityImpl destinationNode) { this.destinationNode = destinationNode; } }
如果有帮助到你,请点赞再走