使用Camunda流程引擎开发,产品提出根据流程节点筛选数据需求,...
在用Camunda流程引擎做业务开发,遇到了各种各样的需求,我扣掉了十根头发,看了很多的星星。今天产品经理不知道吃了什么大米,来到的的位置,说:周周同学,我发现了一个很棒的需求,你要不要听一听?
看着产品经理一脸坏笑,正要拒绝,产品经理继续说道:在流程列表页面,增加一个根据流程节点的筛选条件,这样用户查询的时候是不是更加精准了,我们的系统是不是又完美了很多。我刚要张嘴,产品经理电话响了,是客户的电话。我在一旁就听产品经理吧啦吧啦,大约10分钟过后。产品经理说:刚刚给客户介绍了这个需求,客户非常满意,你今天做好,明天测试,后天就更新到客户系统。说完拍拍我的肩膀,头也不回地走了。看着产品经理越来越小的背影,感觉脑后吹过一阵凉风。我是谁,我在哪里,我要做什么……经过一番思绪整理,不就是增加一个流程节点的列表接口吗?我做还不行嘛,就这样我又……思路整理:
- 根据流程实例ID,获取流程实例 根据流程实例ID,取到定义流程的XML
- 解析流程实例 把XML中的userTask节点解析
- 返回列表数据 把解析出来的节点信息(节点ID,节点名字)组装到LIST返给前端
翻看了 Camunda 源码,发现真的可以优化,接着有了下面的代码:
返回给前端的节点数据实体:
package com.bpm.camunda.vo;
import lombok.Data;
public class ActivityNodeVO {
// 节点ID
private String activityId;
// 节点名字
private String activityName;
}
接口层:
public ResponseStatusDto
> getActivityNodeList(String procId){
if(StringUtils.isBlank(procId)){
return ResponseStatusDto.failure("流程实例ID不能为空");
}
return ResponseStatusDto.success(workflowTaskService.getActivityNodeList(procId));
}
服务层:
public List
getActivityNodeList(String procId) { List
activityNodeVOList = new ArrayList<>(); if(StringUtils.isBlank(procId)){
return activityNodeVOList;
}
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
if(ObjectUtils.isEmpty(historicProcessInstance)){
return activityNodeVOList;
}
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(historicProcessInstance.getProcessDefinitionId());
if(ObjectUtils.isEmpty(bpmnModelInstance)){
return activityNodeVOList;
}
List
domElementList = bpmnModelInstance.getDocument().getRootElement().getChildElements(); if(ObjectUtils.isEmpty(domElementList)){
return activityNodeVOList;
}
DomElement domElement = domElementList.stream().filter(it -> "process".equals(it.getLocalName())).findFirst().orElse(null);
if(ObjectUtils.isEmpty(domElement)){
return activityNodeVOList;
}
activityNodeVOList.addAll(ActivityNodeUtils.createActivityNodeBySubProcessElement(domElement));
return activityNodeVOList;
}
涉及到的工具类:
package com.bpm.utils;
import com.bpm.camunda.vo.ActivityNodeVO;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.model.xml.instance.DomElement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ActivityNodeUtils {
protected static ActivityNodeVO createActivityNodeByTaskElement(DomElement e){
ActivityNodeVO activityNodeVO = new ActivityNodeVO();
activityNodeVO.setActivityId(e.getAttribute("id"));
activityNodeVO.setActivityName(e.getAttribute("name"));
return activityNodeVO;
}
protected static Set
getNodeByActivityInstance(ActivityInstance activityInstance) {if(activityInstance == null){
return new HashSet<>();
}
Set
activityNodeVOSet = new HashSet<>(); ActivityNodeVO activityNodeVO = new ActivityNodeVO();
activityNodeVO.setActivityId(activityInstance.getActivityId());
activityNodeVO.setActivityName(activityInstance.getActivityName());
activityNodeVOSet.add(activityNodeVO);
if(ObjectUtils.isNotEmpty(activityInstance.getChildActivityInstances())){
for (ActivityInstance instance : activityInstance.getChildActivityInstances()){
getNodeByActivityInstance(instance);
}
}
return activityNodeVOSet;
}
public static List
createActivityNodeBySubProcessElement(DomElement e) {List
activityNodeVOList = new ArrayList<>(); e.getChildElements().stream()
.filter(it -> "userTask".equals(it.getLocalName()) || "subProcess".equals(it.getLocalName()))
.forEach(item ->{
switch (item.getLocalName()){
case "userTask":
activityNodeVOList.add(createActivityNodeByTaskElement(item));
break;
case "subProcess":
activityNodeVOList.addAll(createActivityNodeBySubProcessElement(item));
break;
}
});
return activityNodeVOList;
}
}
完成后,调用接口测试:
完成功能,下班回家。本来加班应该有点沮丧,但不知道为什么心里还是有点窃喜,可能这就是做为一名程序的快乐吧!
评论