图例

环境

软件 版本
SpringBoot 1.5.10
activiti-spring-boot-starter-basic 6.0

生成代码

以下是简化代码:

    /**
* 查看实例流程图,根据流程实例ID获取流程图
*/
@RequestMapping(value="traceprocess/{instanceId}",method=RequestMethod.GET)
public void traceprocess(HttpServletResponse response,@PathVariable("instanceId")String instanceId) throws Exception{
InputStream in = flowUtils.getResourceDiagramInputStream(instanceId);
ServletOutputStream output = response.getOutputStream();
IOUtils.copy(in, output);
}

Flow 工具类:

/**
* Flow 工具类
* @author zhipeng.zhang
*/
@Component
public class FlowUtils { @Autowired
RuntimeService runservice;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngineFactoryBean processEngine;
/**
* 获取历史节点流程图
* @param id
* @return
*/
public InputStream getResourceDiagramInputStream(String id) {
try {
// 获取历史流程实例
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
// 获取流程中已经执行的节点,按照执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(id).orderByHistoricActivityInstanceId().asc().list();
// 构造已执行的节点ID集合
List<String> executedActivityIdList = new ArrayList<String>();
for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
executedActivityIdList.add(activityInstance.getActivityId());
}
// 获取bpmnModel
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
// 获取流程已发生流转的线ID集合
List<String> flowIds = this.getExecutedFlows(bpmnModel, historicActivityInstanceList);
// 使用默认配置获得流程图表生成器,并生成追踪图片字符流
ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
//你也可以 new 一个
//DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", null, 2.0);
return imageStream;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} private List<String> getExecutedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
// 流转线ID集合
List<String> flowIdList = new ArrayList<String>();
// 全部活动实例
List<FlowNode> historicFlowNodeList = new LinkedList<FlowNode>();
// 已完成的历史活动节点
List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<HistoricActivityInstance>();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true));
if (historicActivityInstance.getEndTime() != null) {
finishedActivityInstanceList.add(historicActivityInstance);
}
}
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
FlowNode currentFlowNode = null;
for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
// 获得当前活动对应的节点信息及outgoingFlows信息
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();
/**
* 遍历outgoingFlows并找到已已流转的
* 满足如下条件认为已已流转:
* 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转
*/
FlowNode targetFlowNode = null;
if (BpmsActivityTypeEnum.PARALLEL_GATEWAY.getType().equals(currentActivityInstance.getActivityType())
|| BpmsActivityTypeEnum.INCLUSIVE_GATEWAY.getType().equals(currentActivityInstance.getActivityType())) {
// 遍历历史活动节点,找到匹配Flow目标节点的
for (SequenceFlow sequenceFlow : sequenceFlowList) {
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
if (historicFlowNodeList.contains(targetFlowNode)) {
flowIdList.add(sequenceFlow.getId());
}
}
} else {
List<Map<String, String>> tempMapList = new LinkedList<Map<String,String>>();
// 遍历历史活动节点,找到匹配Flow目标节点的
for (SequenceFlow sequenceFlow : sequenceFlowList) {
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
tempMapList.add(UtilMisc.toMap("flowId", sequenceFlow.getId(), "activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime())));
}
}
}
// 遍历匹配的集合,取得开始时间最早的一个
long earliestStamp = 0L;
String flowId = null;
for (Map<String, String> map : tempMapList) {
long activityStartTime = Long.valueOf(map.get("activityStartTime"));
if (earliestStamp == 0 || earliestStamp >= activityStartTime) {
earliestStamp = activityStartTime;
flowId = map.get("flowId");
}
}
flowIdList.add(flowId);
}
}
return flowIdList;
} }

UtilMisc 工具类:

public class UtilMisc {
public static <V, V1 extends V, V2 extends V> Map<String, V> toMap(String name1, V1 value1, String name2, V2 value2) {
return populateMap(new HashMap<String, V>(), name1, value1, name2, value2);
}
@SuppressWarnings("unchecked")
private static <K, V> Map<String, V> populateMap(Map<String, V> map, Object... data) {
for (int i = 0; i < data.length;) {
map.put((String) data[i++], (V) data[i++]);
}
return map;
}
}

工作流枚举类:

/**
* 工作流枚举类
* @author zhipeng.zhang
*/
public enum BpmsActivityTypeEnum { START_EVENT("startEvent", "开始事件"),
END_EVENT("endEvent", "结束事件"),
USER_TASK("userTask", "用户任务"),
EXCLUSIVE_GATEWAY("exclusiveGateway", "排他网关"),
PARALLEL_GATEWAY("parallelGateway", "并行网关"),
INCLUSIVE_GATEWAY("inclusiveGateway", "包含网关"); private String type;
private String name; private BpmsActivityTypeEnum(String type, String name) {
this.type = type;
this.name = name;
} public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

浏览器直接发送以下格式请求,就可以查看实时流程图:

# traceprocess 后面追加流程ID
http://localhost:8080/traceprocess/20190214

最新文章

  1. T-Sql(四)表关联和视图(view)
  2. 用于基于 RPM 的 Linux 平台的 Java
  3. windows环境下,如何启动chromedriver
  4. codevs 1163 访问艺术馆
  5. 使用Git进行代码管理心得
  6. iOS - Swift 与 Objective-C 互相操作
  7. nginx+tomcat集群配置(1)---根目录设定和多后端分发配置
  8. Eclipse 复制按钮卡死
  9. 如何将中国知网CNKI中的文献导入EndNote X6
  10. USB Type-C“三剑客”: 连接器、控制器和电缆
  11. 编写C# Windows服务,用于杀死Zsd.exe进程
  12. Debug与Release有时候确实不一致
  13. MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  14. AppCompat v21 — Android 5.0之前版本设备的Material Design实现
  15. django服务器正常打开,本地localhost能连上,其他计算机却连不上
  16. python线程与进程手记
  17. Best time to buy and sell stocks IV
  18. android 2018 面试题
  19. 我认知的javascript之作用域和闭包
  20. Learn how to use git

热门文章

  1. Get Total Sum Using Multithread Programming
  2. 查找第三方银行官方app下载链接探索过程
  3. Maven常用命令:
  4. 【JVM系列】一步步解析java执行内幕
  5. 第一册:Lesson 123.
  6. .net工具类 获取枚举类型的描述
  7. c# 解决Randoms伪随机重复问题
  8. 折腾Java设计模式之迭代器模式
  9. Web前端 前端相关书籍推荐
  10. ArcGIS API for JavaScript 与 npm 之例子运行