网站首页 > java教程 正文
本篇内容:实时查看当前流程进度。
说明:本篇内容是基于上一篇《Springboot整合工作流引擎Activiti(一) 》,请先阅读上一篇内容
- HolidayService类中添加两个方法:
/**
* <p>查询历史信息</p>
* <p>时间:2021年1月24日-上午10:42:02</p>
* @author baba
* @param instanceId 实例ID
* @return HistoricProcessInstance
*/
public HistoricProcessInstance queryHistory(String instanceId) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult() ;
}
/**
* <p>根据实例ID获取历史活动示例查询器</p>
* <p>时间:2021年1月24日-上午10:45:46</p>
* @author baba
* @param instanceId 实例ID
* @return HistoricActivityInstanceQuery
*/
public HistoricActivityInstanceQuery getHistoryActivity(String instanceId) {
return historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId) ;
}
- 配置流程图生成Bean
@Configuration
public class ActivitiConfig {
@Bean
@ConditionalOnMissingBean
public ProcessDiagramGenerator processDiagramGenerator() {
return new DefaultProcessDiagramGenerator() ;
}
}
- 获取各个节点信息(执行过的)
public class ActivitiUtils {
/**
* <p>
* 获取流程走过的线
* </p>
* <p>时间:2021年1月24日-上午10:52:01</p>
* @author baba
* @param bpmnModel 流程对象模型
* @param processDefinitionEntity 流程定义对象
* @param historicActivityInstances 历史流程已经执行的节点,并已经按执行的先后顺序排序
* @return List<String> 流程走过的线
*/
public static List<String> getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
// 用以保存高亮的线flowId
List<String> highFlows = new ArrayList<String>();
if(historicActivityInstances == null || historicActivityInstances.size() == 0) return highFlows;
// 遍历历史节点
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
// 取出已执行的节点
HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);
// 用以保存后续开始时间相同的节点
List<FlowNode> sameStartTimeNodes = new ArrayList<FlowNode>();
// 获取下一个节点(用于连线)
FlowNode sameActivityImpl = getNextFlowNode(bpmnModel, historicActivityInstances, i, activityImpl_);
// 将后面第一个节点放在时间相同节点的集合里
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<SequenceFlow> 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;
}
/**
* <p>
* 获取下一个节点信息
* </p>
* <p>时间:2021年1月24日-上午10:52:46</p>
* @author baba
* @param bpmnModel 流程模型
* @param historicActivityInstances 历史节点
* @param i 当前已经遍历到的历史节点索引(找下一个节点从此节点后)
* @param activityImpl_ 当前遍历到的历史节点实例
* @return FlowNode 下一个节点信息
*/
private static FlowNode getNextFlowNode(BpmnModel bpmnModel, List<HistoricActivityInstance> 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;
}
}
- 测试Controller
@RestController
@RequestMapping("/view")
public class ProcessViewController {
private static Logger logger = LoggerFactory.getLogger(ProcessViewController.class) ;
@Resource
private HolidayService holidayService ;
@Resource
private RepositoryService repositoryService ;
@Resource
private ProcessDiagramGenerator processDiagramGenerator ;
@ResponseBody
@GetMapping("/image")
public void showImg(String instanceId, HttpServletResponse response) throws Exception {
response.setContentType("text/html;charset=utf-8") ;
if (StringUtils.isEmpty(instanceId)) {
PrintWriter out = response.getWriter() ;
out.write("error") ;
out.close() ;
return ;
}
// 获取流程实例
HistoricProcessInstance processInstance = holidayService.queryHistory(instanceId) ;
if(processInstance == null) {
logger.error("流程实例ID:{}没查询到流程实例!", instanceId);
PrintWriter out = response.getWriter() ;
out.write("error instance not exists") ;
out.close() ;
return;
}
// 根据流程对象获取流程对象模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
// 构造历史流程查询
HistoricActivityInstanceQuery historyInstanceQuery = holidayService.getHistoryActivity(instanceId) ;
// 查看已执行的节点集合,获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
if(historicActivityInstanceList == null || historicActivityInstanceList.isEmpty()) {
logger.error("流程实例ID: {}, 没有历史节点信息!", instanceId) ;
outputImg(response, bpmnModel, null, null) ;
return ;
}
// 已执行的节点ID集合(将historicActivityInstanceList中元素的activityId字段取出封装到executedActivityIdList)
List<String> executedActivityIdList = historicActivityInstanceList.stream().map(item -> item.getActivityId()).collect(Collectors.toList());
// 获取流程定义
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
List<String> flowIds = ActivitiUtils.getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList);
// 输出图像,并设置高亮
outputImg(response, bpmnModel, flowIds, executedActivityIdList);
}
/**
* <p>
* 输出图像
* </p>
* <p>时间:2021年1月24日-上午10:49:42</p>
* @author baba
* @param response
* @param bpmnModel 图像对象
* @param flowIds 已执行的线集合
* @param executedActivityIdList 已执行的节点ID集合
* @return void
*/
private void outputImg(HttpServletResponse response, BpmnModel bpmnModel, List<String> flowIds, List<String> executedActivityIdList) {
InputStream imageStream = null;
try {
imageStream = processDiagramGenerator.generateDiagram(bpmnModel, executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", true, "png");
// 输出资源内容到相应对象
byte[] b = new byte[10 * 1024] ;
int len = -1 ;
while ((len = imageStream.read(b)) != -1) {
response.getOutputStream().write(b, 0, len);
}
response.getOutputStream().flush();
}catch(Exception e) {
logger.error("流程图输出异常!", e);
} finally {
if (imageStream != null) {
try {
imageStream.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
测试:
- 生成一个新的请假流程
调用接口:
/holidays/start?processDefinitionId=holiday:1:0a012ce6-5df2-11eb-afe9-00d861e5b732&userId=10000 - 查看当前用户的任务列表(找出刚启动流程的实例id)
调用接口:
/holidays/tasks?userId=10000
- 查看当前流程图
调用接口:
/view/image?instanceId=341ee217-5df2-11eb-afe9-00d861e5b732
- 继续执行下一步流程
调用接口:
/holidays/apply?days=3&mgr=10001&explain=生病&instanceId=341ee217-5df2-11eb-afe9-00d861e5b732
- 查看当前流程图
调用接口:
/view/image?instanceId=341ee217-5df2-11eb-afe9-00d861e5b732
到此完毕!!!
各位好心人给个关注+转发好不好谢谢了
猜你喜欢
- 2024-10-27 30分钟学会:springboot+mysql+camunda开源工作流引擎
- 2024-10-27 详解JavaEE中级程序员路线图,其涉及课程资源已更新
- 2024-10-27 吐血推荐一款开源工作流引擎:camunda使用入门
- 2024-10-27 工作流引擎开发系列一基础知识(工作流引擎的好处)
- 2024-10-27 超轻量级工作流引擎,只要七张表就解决工作流ingens...
- 2024-10-27 Windmill:最快的自托管开源工作流引擎
- 2024-10-27 流程智慧:低代码开发平台工作流引擎的技术原理解析
- 2024-10-27 工作流引擎的工作原理与功能(工作流引擎是什么意思)
- 2024-10-27 免费开源,一款快速开发模块化脚手架,含工作流引擎
- 2024-10-27 LeaRun .Net Core/Java工作流引擎,分离式前端,升级Vue
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)