Activit的心路历程:Activiti6.0获取当前节点的下一节点【可能存在多个】的nodeId

8 篇文章 1 订阅
8 篇文章 1 订阅

上一任务节点

注意:当前操作需要具备activiti6.0的基础

在我的开发中,突然给我提出了一个待办任务需要获取当前任务节点下一任务节点的表单信息,刚开始搞得我有点措手不及,后来仔细思考后,灵感一下,直接操作流程的bpmn信息就可以获取到节点信息嘛,顺着这个思路,我整理出了自己的思路:
(1)将节点大体分为两类,一类是网关节点,另外一类就是用户任务节点,使用List集合,将网关与用户任务进行分类
(2)获取上一节点,我们就需要从bpmn的连线信息入手,这次我们获取的是UserTask节点的出线,固定连线的sourceRef,辨别节点targtaetRef的类型,当是用户任务时,放进 List behildNodeIdlist= new ArrayList<>();,当是GateWay节点时,将sourceRef设为网关的,继续遍历下一节点,就是跳过网关节点,只要用户任务节点

下面是我的测试代码【我使用springboot为基础测试环境】

 	@Test
    public void behindNode() {
        //        String nodeId="UserTask_0mkm9h7";
        String nodeId = "UserTask_0mkm9h7";
        String processInstanceId="2205001";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        String processDefinitionId=processInstance.getProcessDefinitionId();
        List<String> behildNodeIdlist=getBehindNodeIdByNodeId(nodeId,processDefinitionId);
        behildNodeIdlist.forEach(System.out::println);
    }


 	/**
     * 获取当前节点下一节点id(只能获取UserTask类型的)【可能多个节点id】
     * 通过taskId获取当前节点的下一节点id
     *
     * @param taskId
     * @return
     */
    public List<String> getBehindNodeIdByTaskId(String taskId) {
        ProcessEngine defaultProcessEngine = getProcessEngine();
        HistoryService historyService = defaultProcessEngine.getHistoryService();
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        String nodeId = task.getTaskDefinitionKey();
        String processDefinitionId = task.getProcessDefinitionId();
        return getBehindNodeIdByNodeId(nodeId, processDefinitionId);
    }
	

  public ProcessEngine getProcessEngine() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        return defaultProcessEngine;
    }

   private BpmnModel getBpmnModel(String processDefinitionId) {
        ProcessEngine processEngine = getProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        return repositoryService.getBpmnModel(processDefinitionId);
    }


    /**
     * 通过nodeId与流程定义Id,获取当前节点的下一节点id,默认开启过滤
     *
     * @param nodeId
     * @param processDefinitionId
     * @return
     */
    public List<String> getBehindNodeIdByNodeId(String nodeId, String processDefinitionId) {
        return getBehindNodeIdByNodeIdFilter(nodeId, processDefinitionId, true);
    }

  	/**
     * 通过nodeId与流程定义Id,获取当前节点的下一节点id
     *
     * @param nodeId
     * @param processDefinitionId
     * @param isFilterEndEvent    是否开启过滤掉EndEvent节点
     * @return
     */
    public List<String> getBehindNodeIdByNodeIdFilter(String nodeId, String processDefinitionId, boolean isFilterEndEvent) {
        BpmnModel bpmnModel = getBpmnModel(processDefinitionId);
        return getBehindNodeIdByNodeIdFilterRam(bpmnModel, nodeId, processDefinitionId, isFilterEndEvent);
    }

    public List<String> getBehindNodeIdByNodeIdFilterRam(BpmnModel bpmnModel, String nodeId, String processDefinitionId, boolean isFilterEndEvent) {
        //网关集合
        List<Gateway> gateways = new ArrayList<>();
        //用户任务集合
        List<UserTask> userTasks = new ArrayList<>();
        //网关节点id
        List<String> gatewayNodelIdList = new ArrayList<>();
        //用户任务节点id
        List<String> usertaskNodelIdList = new ArrayList<>();

        List<Process> processes = bpmnModel.getProcesses();
        Process process = processes.get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();

        //放置endEvent的nodeId
        AtomicReference<String> endEventId = new AtomicReference<>("");

        //将网关信息与用户任务进行分类存储(放于JVM堆中)
        flowElements.forEach(flowElement -> {
            if (flowElement instanceof Gateway) {
                gatewayNodelIdList.add(flowElement.getId());
                gateways.add((Gateway) flowElement);
            }
            if (flowElement instanceof UserTask) {
                usertaskNodelIdList.add(flowElement.getId());
                userTasks.add((UserTask) flowElement);
            }
            if (flowElement instanceof EndEvent) {
                endEventId.set(flowElement.getId());
            }
        });

        //存放下一节点的nodeId(可能存在多个)
        List<String> behildNodeIdlist = new ArrayList<>();
        //空间换时间 nodeId-GatewayObj
        Map<String, Gateway> gatewayMap = gateways.stream().collect(Collectors.toMap(Gateway::getId, v -> v));

        //变量所有的UserTask节点
        for (UserTask userTask : userTasks) {
            //获取UserTask节点的出线
            List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
            for (SequenceFlow outgoingFlow : outgoingFlows) {
                String sourceRef = outgoingFlow.getSourceRef();
                String targetRef = outgoingFlow.getTargetRef();
                //固定出线的(sourceRef)
                if (nodeId.equals(sourceRef)) {
                    collectBehindNodeIds(isFilterEndEvent, gatewayMap, gatewayNodelIdList, endEventId, behildNodeIdlist, targetRef);
                }
            }

        }

        return behildNodeIdlist;
    }

	/**
	* 使用递归,每次多向下多看一个节点
	*/
    private void collectBehindNodeIds(boolean isFilterEndEvent, Map<String, Gateway> gatewayMap, List<String> gatewayNodelIdList, AtomicReference<String> endEventId, List<String> behildNodeIdlist, String targetRef) {
        //当前节点的下一节点是网关,跳过
        if (gatewayNodelIdList.contains(targetRef)) {
            Gateway gateway = gatewayMap.get(targetRef);
            //获取网关的出线信息
            List<SequenceFlow> outgoingFlowsGateWay = gateway.getOutgoingFlows();
            for (SequenceFlow sequenceFlow : outgoingFlowsGateWay) {
                String sourceRefGateWay = sequenceFlow.getSourceRef();
                String targetRefGateWay = sequenceFlow.getTargetRef();
                boolean isNotEndEvent = true;
                if (isFilterEndEvent) {
                    isNotEndEvent = !targetRefGateWay.equals(endEventId.get());
                }
                //判断下一节点是否是endEvent
                if (isNotEndEvent) {
                    //nodeId指向targetRef继续向下搜索
                    collectBehindNodeIds(isFilterEndEvent, gatewayMap, gatewayNodelIdList, endEventId, behildNodeIdlist, targetRefGateWay);
                }
            }
        } else {
            boolean isNotEndEvent = true;
            if (isFilterEndEvent) {
                isNotEndEvent = !targetRef.equals(endEventId.get());
            }
            //判断下一节点是否是endEvent
            if (isNotEndEvent) {
                behildNodeIdlist.add(targetRef);
            }
        }
    }

我使用的测试流程bpmn如下

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://activiti.org/bpmn">
  <process id="Process_1" name="测试流程" isExecutable="true">
    <startEvent id="StartEvent_1b9bgjv" name="start"></startEvent>
    <userTask id="UserTask_1wba62u" name="faqi" activiti:assignee="people1">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="SequenceFlow_1fnj22n" sourceRef="StartEvent_1b9bgjv" targetRef="UserTask_1wba62u"></sequenceFlow>
    <parallelGateway id="ParallelGateway_0g393ev"></parallelGateway>
    <userTask id="UserTask_1nt87by" name="tb1" activiti:assignee="people2">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="UserTask_1xty4gu" name="tb2" activiti:assignee="people3">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="UserTask_0y14rmq" name="sp1" activiti:assignee="people4">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="UserTask_17jd9y1" name="sp2" activiti:assignee="people5">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <parallelGateway id="ParallelGateway_1qs7f87"></parallelGateway>
    <endEvent id="EndEvent_0fo9mwb" name="交易完成"></endEvent>
    <sequenceFlow id="SequenceFlow_1dkxqia" sourceRef="UserTask_1wba62u" targetRef="ParallelGateway_0g393ev"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_1pp85s1" sourceRef="ParallelGateway_0g393ev" targetRef="UserTask_1nt87by"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_1x051ae" sourceRef="ParallelGateway_0g393ev" targetRef="UserTask_1xty4gu"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_05zxco5" sourceRef="UserTask_1nt87by" targetRef="UserTask_0y14rmq"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_0bx5wt0" sourceRef="UserTask_1xty4gu" targetRef="UserTask_17jd9y1"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_0xgm2pr" sourceRef="UserTask_17jd9y1" targetRef="ParallelGateway_1qs7f87"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_1o2rph4" sourceRef="UserTask_0y14rmq" targetRef="ParallelGateway_1qs7f87"></sequenceFlow>
    <sequenceFlow id="SequenceFlow_1hyky18" sourceRef="ParallelGateway_1qs7f87" targetRef="UserTask_0mkm9h7"></sequenceFlow>
    <userTask id="UserTask_0mkm9h7" name="spe" activiti:assignee="people6">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="SequenceFlow_1smv331" sourceRef="UserTask_0mkm9h7" targetRef="EndEvent_0fo9mwb"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_Process_1">
    <bpmndi:BPMNPlane bpmnElement="Process_1" id="BPMNPlane_Process_1">
      <bpmndi:BPMNShape bpmnElement="StartEvent_1b9bgjv" id="BPMNShape_StartEvent_1b9bgjv">
        <omgdc:Bounds height="36.0" width="36.0" x="182.0" y="222.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_1wba62u" id="BPMNShape_UserTask_1wba62u">
        <omgdc:Bounds height="80.0" width="100.0" x="270.0" y="200.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="ParallelGateway_0g393ev" id="BPMNShape_ParallelGateway_0g393ev">
        <omgdc:Bounds height="50.0" width="50.0" x="425.0" y="215.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_1nt87by" id="BPMNShape_UserTask_1nt87by">
        <omgdc:Bounds height="80.0" width="100.0" x="540.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_1xty4gu" id="BPMNShape_UserTask_1xty4gu">
        <omgdc:Bounds height="80.0" width="100.0" x="540.0" y="260.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_0y14rmq" id="BPMNShape_UserTask_0y14rmq">
        <omgdc:Bounds height="80.0" width="100.0" x="710.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_17jd9y1" id="BPMNShape_UserTask_17jd9y1">
        <omgdc:Bounds height="80.0" width="100.0" x="710.0" y="260.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="ParallelGateway_1qs7f87" id="BPMNShape_ParallelGateway_1qs7f87">
        <omgdc:Bounds height="50.0" width="50.0" x="865.0" y="205.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="EndEvent_0fo9mwb" id="BPMNShape_EndEvent_0fo9mwb">
        <omgdc:Bounds height="36.0" width="36.0" x="1162.0" y="212.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="UserTask_0mkm9h7" id="BPMNShape_UserTask_0mkm9h7">
        <omgdc:Bounds height="80.0" width="100.0" x="990.0" y="190.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1pp85s1" id="BPMNEdge_SequenceFlow_1pp85s1">
        <omgdi:waypoint x="450.0" y="215.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="180.0"></omgdi:waypoint>
        <omgdi:waypoint x="540.0" y="180.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_0xgm2pr" id="BPMNEdge_SequenceFlow_0xgm2pr">
        <omgdi:waypoint x="810.0" y="300.0"></omgdi:waypoint>
        <omgdi:waypoint x="890.0" y="300.0"></omgdi:waypoint>
        <omgdi:waypoint x="890.0" y="255.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1dkxqia" id="BPMNEdge_SequenceFlow_1dkxqia">
        <omgdi:waypoint x="370.0" y="240.0"></omgdi:waypoint>
        <omgdi:waypoint x="425.0" y="240.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_05zxco5" id="BPMNEdge_SequenceFlow_05zxco5">
        <omgdi:waypoint x="640.0" y="180.0"></omgdi:waypoint>
        <omgdi:waypoint x="710.0" y="180.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1x051ae" id="BPMNEdge_SequenceFlow_1x051ae">
        <omgdi:waypoint x="450.0" y="265.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="300.0"></omgdi:waypoint>
        <omgdi:waypoint x="540.0" y="300.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1o2rph4" id="BPMNEdge_SequenceFlow_1o2rph4">
        <omgdi:waypoint x="810.0" y="180.0"></omgdi:waypoint>
        <omgdi:waypoint x="890.0" y="180.0"></omgdi:waypoint>
        <omgdi:waypoint x="890.0" y="205.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_0bx5wt0" id="BPMNEdge_SequenceFlow_0bx5wt0">
        <omgdi:waypoint x="640.0" y="300.0"></omgdi:waypoint>
        <omgdi:waypoint x="710.0" y="300.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1smv331" id="BPMNEdge_SequenceFlow_1smv331">
        <omgdi:waypoint x="1090.0" y="230.0"></omgdi:waypoint>
        <omgdi:waypoint x="1162.0" y="230.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1fnj22n" id="BPMNEdge_SequenceFlow_1fnj22n">
        <omgdi:waypoint x="218.0" y="240.0"></omgdi:waypoint>
        <omgdi:waypoint x="270.0" y="240.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="SequenceFlow_1hyky18" id="BPMNEdge_SequenceFlow_1hyky18">
        <omgdi:waypoint x="915.0" y="230.0"></omgdi:waypoint>
        <omgdi:waypoint x="990.0" y="230.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
Activiti中,要根据当前节点获取下一个节点信息,通常涉及的是业务流程引擎的执行上下文。当你开始执行一个流程实例,并到达某个特定节点时,你可以查询它的后续流程元素。以下是一个基本步骤: 1. **启动流程实例**: 首先,使用`ActivitiRepositoryService`或`RuntimeService`启动一个新的流程实例。这会创建一个流程实例,并将其状态设置为“正在运行”。 ```java ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("yourProcessKey"); ``` 2. **获取当前活动**: 使用`RuntimeService`的`getCurrentActivityId()`方法,获取当前执行的活动ID。 ```java String currentActivityId = runtimeService.getCurrentActivityId(); ``` 3. **查询下一节点**: 可以使用`HistoricActivityInstanceQuery`或者`RuntimeActivityQuery`,根据当前活动ID找到其后的直接连接(边)或决策流。例如,查询下一个用户任务或流程决策节点: ```java HistoricActivityInstance nextActivity = historyService.createHistoricActivityInstanceQuery() .activityInstanceId(currentActivityId) .next(0) // 获取第一个下一个活动 .singleResult(); if (nextActivity != null) { String nextActivityId = nextActivity.getActivityId(); // 获取下一步节点的信息 Map<String, Object> variables = runtimeService.getVariables(processInstance.getId()); // 或者查询任务相关的属性,如任务标题 UserTask task = taskService.createTaskQuery().taskId(nextActivityId).singleResult(); String taskTitle = task.getTitle(); } ``` 4. **处理分支或循环**: 如果流程图包含分支,你需要考虑下一个活动可能是基于条件判断的结果。这时可能需要使用`HistoricVariableInstanceQuery`查找变量的值来决定流程走向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值