activiti 流程节点调用完成后继续_Activiti精品 悟纤出品Activiti7之流程跟踪与流程图展示 第333篇...

本文详细介绍了在Activiti中实现流程跟踪与流程图展示的方法,包括获取流程引擎、流程图生成器、流程模型,以及如何通过HttpServletResponse输出流程图。通过示例代码展示了如何在SpringBoot应用中展示当前流程状态,并提供了测试和实际应用的步骤。
摘要由CSDN通过智能技术生成

关历史文章(阅读本文前,您可能需要先看下之前的系列?)

国内最全的Spring Boot系列之三

2020上半年发文汇总「值得收藏」

「工作流Activiti」介绍-新手上路,注意安全 - 第320篇

「Activiti精品 悟纤出品」activiti介绍-十万个为什么 - 第321篇

「Activiti精品 悟纤出品」Activiti6 Getting Started- 稳扎稳打 - 第322篇

「Activiti精品 悟纤出品」Activiti7 Getting Started-摸石头过河 - 第323篇

「Activiti精品 悟纤出品」流程模型搭建-小试牛刀 - 第324篇

「Activiti精品 悟纤出品」基于mysql初始化「图图为啥消失了」- 第325篇

「Activiti精品 悟纤出品」Activiti插件来助你一臂之力 - 第327篇

「Activiti精品 悟纤出品」核心类以及如何在SpringBoot集成说明 - 第328篇

「Activiti精品 悟纤出品」开发一个简单的SpringBoot activiti应用 - 第330篇

「Activiti精品 悟纤出品」Activiti7数据库表 - 第332篇

师傅:上面我们已经跑通了整个流程了,但是对于用户而言,是不是很想知道这个流程都是怎么流转的,都需要什么人进行审批,目前到哪个环节了。

3b61d5489652321848a139dc0d94e4f7.png

悟纤:这个需求应该很有必要呐,不然用户对于无期望的等待会很难受呢。

eea3a0d6fae88ebace3a5cf158dc89d8.png

师傅:你等妹子也会很难受吗?

4004845c12ee1daa0092fa7dd4db18b3.png

悟纤:师傅你好坏也。

d0011c9bbc459d3aa4bf1080395bfb2e.png

师傅:好了,不逗你了,咱们赶紧进入正题吧。                             

6faab8174a82832e9c6b5810e9cbb094.gif

前言

         这一节我们要讲一下流程跟踪与流程图展示,怎么是流程跟踪,你还不知道嘛,不可能也,我们之前有一张漂亮的图片,你没有细看吧。

dd9e1c92a3d8e4eec3a51abec8ecf5c2.png

         很好看吧?矣矣,放错了,是这张:

6de9d46513eb07bbac48ba8935f78ace.png

我们在使用activiti-app的时候,在流程的过程中有一个按钮【Show diagram】查看流程当前流转状态。

那么在项目路中怎么展示这个流程图呐?整个思路也是很简单的。

一、流程跟踪与流程图展示

1.1 说明

         这个我们是在前面的文章

《「Activiti精品悟纤出品」开个一个简单的SpringBoot activiti应用》

         接着往上进行添加代码的,所以如果你没有,你懂得….

         大致的思路就是:

(1)获取流程引擎

(2)获取流程引擎配置实现类

(3)通过流程引擎配置实现类获取图片默认生成器ProcessDiagramGenerator

(4)获取流程模型BpmnModel

(5)创建需要高亮展示的节点的集合,元素为节点ID值

(6)调用ProcessDiagramGenerator的generateDiagram获取生成图片的输入流

(7)客户端展示

1.2 添加依赖

         添加Activiti生成流程图的依赖:

<dependency>    <groupId>org.activitigroupId>    <artifactId>activiti-image-generatorartifactId>    <version>7.1.0.M6version>dependency>

1.3 Activiti工作流工具类

         我们新建一个Activiti工作流工具类,我们先看下源码:

package com.kfit.springbootactiviti7demo.controller;import java.util.ArrayList;import java.util.List;import org.activiti.bpmn.model.BpmnModel;import org.activiti.bpmn.model.FlowNode;import org.activiti.bpmn.model.SequenceFlow;import org.activiti.engine.history.HistoricActivityInstance;import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;/** * 

Activiti工作流工具类

* @author 悟纤【公众号SpringBoot】 */public class ActivitiUtils { /** *

获取流程走过的线

* @param bpmnModel 流程对象模型 * @param processDefinitionEntity 流程定义对象 * @param historicActivityInstances 历史流程已经执行的节点,并已经按执行的先后顺序排序 * @return List 流程走过的线 * @author 悟纤【公众号SpringBoot】 */ public static List getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List historicActivityInstances) { // 用以保存高亮的线flowId List highFlows = new ArrayList(); if(historicActivityInstances == null || historicActivityInstances.size() == 0) return highFlows; // 遍历历史节点 for (int i = 0; i < historicActivityInstances.size() - 1; i++) { // 取出已执行的节点 HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i); // 用以保存后续开始时间相同的节点 List sameStartTimeNodes = new ArrayList(); // 获取下一个节点(用于连线) FlowNode sameActivityImpl = getNextFlowNode(bpmnModel, historicActivityInstances, i, activityImpl_);// FlowNode sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i + 1).getActivityId()); // 将后面第一个节点放在时间相同节点的集合里 if(sameActivityImpl != null) sameStartTimeNodes.add(sameActivityImpl); // 循环后面节点,看是否有与此后继节点开始时间相同的节点,有则添加到后继节点集合 for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) { HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点 HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点 if (activityImpl1.getStartTime().getTime() != activityImpl2.getStartTime().getTime()) break; // 如果第一个节点和第二个节点开始时间相同保存 FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId()); sameStartTimeNodes.add(sameActivityImpl2); } // 得到节点定义的详细信息 FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId()); // 取出节点的所有出去的线,对所有的线进行遍历 List pvmTransitions = activityImpl.getOutgoingFlows(); for (SequenceFlow pvmTransition : pvmTransitions) { // 获取节点 FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef()); // 不是后继节点 if(!sameStartTimeNodes.contains(pvmActivityImpl)) continue; // 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示 highFlows.add(pvmTransition.getId()); } } //返回高亮的线 return highFlows; } /** *

获取下一个节点信息

* @param bpmnModel 流程模型 * @param historicActivityInstances 历史节点 * @param i 当前已经遍历到的历史节点索引(找下一个节点从此节点后) * @param activityImpl_ 当前遍历到的历史节点实例 * @return FlowNode 下一个节点信息 * @author 悟纤【公众号SpringBoot】 */ private static FlowNode getNextFlowNode(BpmnModel bpmnModel, List historicActivityInstances, int i, HistoricActivityInstance activityImpl_) { // 保存后一个节点 FlowNode sameActivityImpl = null; // 如果当前节点不是用户任务节点,则取排序的下一个节点为后续节点 if(!"userTask".equals(activityImpl_.getActivityType())) { // 是最后一个节点,没有下一个节点 if(i == historicActivityInstances.size()) return sameActivityImpl; // 不是最后一个节点,取下一个节点为后继节点 sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i + 1).getActivityId());// 找到紧跟在后面的一个节点 // 返回 return sameActivityImpl; } // 遍历后续节点,获取当前节点后续节点 for (int k = i + 1; k <= historicActivityInstances.size() - 1; k++) { // 后续节点 HistoricActivityInstance activityImp2_ = historicActivityInstances.get(k); // 都是userTask,且主节点与后续节点的开始时间相同,说明不是真实的后继节点 if("userTask".equals(activityImp2_.getActivityType()) && activityImpl_.getStartTime().getTime() == activityImp2_.getStartTime().getTime()) continue; // 找到紧跟在后面的一个节点 sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId()); break; } return sameActivityImpl; }}

说明:

这里主要是获取流程走过的节点,代码中已经添加了很详细的注释,这里不过多进行解释。

1.4 输出图像

         在LeaveController中进行编写输出图像的方法,主要使用HttpServletResponse输出流,这个图片流是通过activiti的processDiagramGenerator进行构建的,具体的源码如下:

/**   * 

输出图像

* @param response 响应实体* @param bpmnModel 图像对象* @param flowIds 已执行的线集合* @param executedActivityIdList void 已执行的节点ID集合* @author 悟纤【公众号SpringBoot】 */ private void outputImg(HttpServletResponse response, BpmnModel bpmnModel, List flowIds, List executedActivityIdList) { InputStream imageStream = null; ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator(); try { imageStream = processDiagramGenerator.generateDiagram(bpmnModel, executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", true, "png"); // 输出资源内容到相应对象 byte[] b = new byte[1024]; int len; while ((len = imageStream.read(b, 0, 1024)) != -1) { response.getOutputStream().write(b, 0, len); } response.getOutputStream().flush(); }catch(Exception e) { e.printStackTrace(); } finally { // 流关闭 if(imageStream != null){ try { imageStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }

1.5 查看当前流程图

         好了,到这里就差不多了,最后在LeaveController编写一个可以访问的链接即可,当然在这里也有一些代码需要编写,如下源码如下:

添加Activiti的RepositoryService,用于获取流程模型:

//org.activiti.engine.impl.RepositoryServiceImpl@Autowiredprivate RepositoryService repositoryService;

         具体的源码如下:

/** * 

查看当前流程图

* @param instanceId 流程实例 * @param response void 响应 * @author 悟纤【公众号SpringBoot】 */@ResponseBody@RequestMapping(value="/showImg")public void showImg(String instanceId, HttpServletResponse response) { /* * 参数校验 */ System.out.println("查看完整流程图!流程实例ID:"+instanceId); if(StringUtils.isBlank(instanceId)) return; /* * 获取流程实例 */ HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult(); if(processInstance == null) { System.out.println("流程实例ID:"+instanceId+"没查询到流程实例!"); return; } // 根据流程对象获取流程对象模型 BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); /* * 查看已执行的节点集合 * 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序 */ // 构造历史流程查询 HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId); // 查询历史节点 List historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list(); if(historicActivityInstanceList == null || historicActivityInstanceList.size() == 0) { System.out.println("流程实例ID:"+instanceId+"没有历史节点信息!"); outputImg(response, bpmnModel, null, null); return; } // 已执行的节点ID集合(将historicActivityInstanceList中元素的activityId字段取出封装到executedActivityIdList) List executedActivityIdList = historicActivityInstanceList.stream().map(item -> item.getActivityId()).collect(Collectors.toList()); /* * 获取流程走过的线 */ // 获取流程定义 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processInstance.getProcessDefinitionId()); List flowIds = ActivitiUtils.getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList); /* * 输出图像,并设置高亮 */ outputImg(response, bpmnModel, flowIds, executedActivityIdList);}

1.6 测试

         好了来测试下,访问地址:

http://127.0.0.1:8080/leave/showImg?instanceId=9e74a46a-eb65-11ea-a6ae-f27b0fd3aed5

         这里有一个实例ID,这个id是我们在访问

http://127.0.0.1:8080/leave/start?jobNumber=A1001

         在浏览器端看到的示例id,最终的结果是:

be20c5222ac1a94fa39dc77477e684d3.png

         红色代表已经是到结束的节点或者正在进行中的节点。

二、悟纤小结

师傅:好了,到这里就实现了,至于能够能够改变流程图的颜色呐,是可以的,需要重写底层一些东西,这个徒儿你自己实现吧,不然都给你搞定了,你以后自己都不会搞了。

悟纤:师傅,你这是要考验我的解决问题的能力吧。

师傅:师傅领进门,修行靠自身。

206099a769514fbec2dbf645190bd008.png

悟纤:好的,我加油搞。

a644127806181b2c1ac4df3ac26a30cf.png

师傅:嗯,那你给大家总结下这节的内容吧。

悟纤:乐意至极。

(1)流程图跟踪和流程图展示的核心就是使用activiti提供的ProcessDiagramGenerator进行生成图片,对于数据的话,需要通过获取activiti的数据节点进行绘制。

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à悟空学院:https://t.cn/Rg3fKJD

学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!

SpringBoot视频:http://t.cn/A6ZagYTi

Spring Cloud视频:http://t.cn/A6ZagxSR

SpringBoot Shiro视频:http://t.cn/A6Zag7IV

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringData和JPA视频:http://t.cn/A6Zad1OH

SpringSecurity5.0视频:http://t.cn/A6ZadMBe

ShardingJDBC分库分表:http://t.cn/A6ZarrqS

分布式事务解决方案:http://t.cn/A6ZaBnIr

JVM内存模型调优实战:http://t.cn/A6wWMVqG

Spring入门到精通:https://t.cn/A6bFcDh4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值