使用Camunda流程引擎开发,产品提出根据流程节点筛选数据需求,...

共 4583字,需浏览 10分钟

 ·

2022-02-20 09:57

a1a05eeb9834b5d350fef7ce6c339f14.webp
在用Camunda流程引擎做业务开发,遇到了各种各样的需求,我扣掉了十根头发,看了很多的星星。今天产品经理不知道吃了什么大米,来到的的位置,说:周周同学,我发现了一个很棒的需求,你要不要听一听?
看着产品经理一脸坏笑,正要拒绝,产品经理继续说道:在流程列表页面,增加一个根据流程节点的筛选条件,这样用户查询的时候是不是更加精准了,我们的系统是不是又完美了很多。我刚要张嘴,产品经理电话响了,是客户的电话。我在一旁就听产品经理吧啦吧啦,大约10分钟过后。产品经理说:刚刚给客户介绍了这个需求,客户非常满意,你今天做好,明天测试,后天就更新到客户系统。说完拍拍我的肩膀,头也不回地走了。看着产品经理越来越小的背影,感觉脑后吹过一阵凉风。我是谁,我在哪里,我要做什么……经过一番思绪整理,不就是增加一个流程节点的列表接口吗?我做还不行嘛,就这样我又……思路整理:


  1. 根据流程实例ID,获取流程实例    根据流程实例ID,取到定义流程的XML
  2. 解析流程实例   把XML中的userTask节点解析
  3. 返回列表数据   把解析出来的节点信息(节点ID,节点名字)组装到LIST返给前端          
OK,也不是很难吗?于是我开始查表,获取到定义流程的XML字符串,完成解析,并返给前端。一顿猛如虎的操作之后,功能完成了。一测试,发现接口响应有点慢,但能接受!(能不慢嘛,又是查表,又是解析XML,一个接口做了这么多的事情。)虽然功能了,但看着数百行的代码,我真的乱了!能不能有更好的方法,我思考着……!!6699bb5d881bf4764ebed9dc1adb9542.webp
翻看了 Camunda 源码,发现真的可以优化,接着有了下面的代码:
返回给前端的节点数据实体:
package com.bpm.camunda.vo;import lombok.Data;@Datapublic class ActivityNodeVO {    // 节点ID    private String activityId;    // 节点名字    private String activityName;}

  接口层:
@ApiOperation("获取流程用户任务节点信息")@GetMapping("/getActivityNodeList")@ApiImplicitParam(name = "procId", value = "流程实例Id", required = true)public ResponseStatusDto> getActivityNodeList(String procId){    if(StringUtils.isBlank(procId)){        return ResponseStatusDto.failure("流程实例ID不能为空");    }    return ResponseStatusDto.success(workflowTaskService.getActivityNodeList(procId));}


服务层:
@Overridepublic 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;    }}


完成后,调用接口测试:41781952edc15fd73b5358295ba1dbfa.webp
完成功能,下班回家。本来加班应该有点沮丧,但不知道为什么心里还是有点窃喜,可能这就是做为一名程序的快乐吧!
浏览 62
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报