Flowable & 网关(二)

808 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

1.包容网关

1.1 什么是包容网关

可以把包容网关(inclusive gateway) 看做排他网关与并行网关的组合。与排他网关一样,可以在包容网关的出口顺序流上定义条件,包容网关会计算条件。然而主要的区别是,包容网关与并行网关一样,可以同时选择多于一条出口顺序流。

包容网关的功能取决于其入口与出口顺序流:

  • 分支: 流程会计算所有出口顺序流的条件。对于每一条计算为true的顺序流,流程都会创建一个并行执行。
  • 合并: 所有到达包容网关的并行执行,都会在网关处等待。直到每一条具有流程标志(process token)的入口顺序流,都有一个执行到达。这是与并行网关的重要区别。换句话说,包容网关只会等待可以被执行的入口顺序流。在合并后,流程穿过合并并行网关继续。 请注意,如果包容网关同时具有多条入口与出口顺序流,可以同时具有分支与合并的行为。在这种情况下,网关首先合并所有具有流程标志的入口顺序流,然后为每一个条件计算为true的出口顺序流分裂出并行执行路径。

包容网关的汇聚行为比并行网关更复杂。所有到达包容网关的并行执行,都会在网关等待,直到所有“可以到达”包容网关的执行都“到达”包容网关。 判断方法为:计算当前流程实例中的所有执行,检查从其位置是否有一条到达包容网关的路径(忽略顺序流上的任何条件)。如果存在这样的执行(可到达但尚未到达),则不会触发包容网关的汇聚行为。

1.2 创建流程图

image.png 流程图xml文件

<?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:flowable="http://flowable.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://www.flowable.org/processdef">
  <process id="Inclusive_gateway" name="包容网关" isExecutable="true">
    <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
    <userTask id="sid-B6DF18F4-A924-4416-9AEB-92B36AEDDD47" name="员工请假" flowable:assignee="zhangsan" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-08FC379C-107A-4867-ACC7-C7DD7F6ADFA0" sourceRef="startEvent1" targetRef="sid-B6DF18F4-A924-4416-9AEB-92B36AEDDD47"></sequenceFlow>
    <inclusiveGateway id="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4"></inclusiveGateway>
    <sequenceFlow id="sid-7A5207E3-A904-4A98-9C3A-9900907194D3" sourceRef="sid-B6DF18F4-A924-4416-9AEB-92B36AEDDD47" targetRef="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4"></sequenceFlow>
    <userTask id="sid-4957D55D-ADC6-487B-90D9-624F05C8A701" name="组长审批" flowable:assignee="lisi" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="sid-2E0ED4DF-906A-462E-9870-CEE680EF5850" name="人事审批" flowable:assignee="wangwu" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="sid-80018531-8ED9-465D-98BB-FA2099D7FF53" name="经理审批" flowable:assignee="zz" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <inclusiveGateway id="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466"></inclusiveGateway>
    <sequenceFlow id="sid-9738C454-8C67-40F5-A476-AB4B21002BD5" sourceRef="sid-4957D55D-ADC6-487B-90D9-624F05C8A701" targetRef="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466"></sequenceFlow>
    <userTask id="sid-147019FA-10BA-4515-9C48-0DC8EABCE4A3" name="财务审批" flowable:assignee="mon" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-E5600212-5D8F-4367-9DCD-5CDCD302DB36" sourceRef="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466" targetRef="sid-147019FA-10BA-4515-9C48-0DC8EABCE4A3"></sequenceFlow>
    <endEvent id="sid-917A8382-52D5-4FAD-B63E-7128AF17642D"></endEvent>
    <sequenceFlow id="sid-0247BC34-F747-4072-B43C-D9A2A9C819CB" sourceRef="sid-147019FA-10BA-4515-9C48-0DC8EABCE4A3" targetRef="sid-917A8382-52D5-4FAD-B63E-7128AF17642D"></sequenceFlow>
    <sequenceFlow id="sid-739AC77C-B5D2-47D4-9B46-B5187B30F257" sourceRef="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4" targetRef="sid-4957D55D-ADC6-487B-90D9-624F05C8A701">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${num<3}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-2FFD0B50-091B-4F52-8CE0-F59B43022217" sourceRef="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4" targetRef="sid-80018531-8ED9-465D-98BB-FA2099D7FF53">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${num>=3}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-1B7BF3D8-5D8B-43F3-B506-552851D59500" sourceRef="sid-80018531-8ED9-465D-98BB-FA2099D7FF53" targetRef="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466"></sequenceFlow>
    <sequenceFlow id="sid-7FB255C5-72F9-401A-B87D-5BBAFCA32607" sourceRef="sid-2E0ED4DF-906A-462E-9870-CEE680EF5850" targetRef="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466"></sequenceFlow>
    <sequenceFlow id="sid-E0E06131-6A7A-41E5-BC68-632698AF1EF3" sourceRef="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4" targetRef="sid-2E0ED4DF-906A-462E-9870-CEE680EF5850"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_Inclusive_gateway">
    <bpmndi:BPMNPlane bpmnElement="Inclusive_gateway" id="BPMNPlane_Inclusive_gateway">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="75.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-B6DF18F4-A924-4416-9AEB-92B36AEDDD47" id="BPMNShape_sid-B6DF18F4-A924-4416-9AEB-92B36AEDDD47">
        <omgdc:Bounds height="80.0" width="100.0" x="240.0" y="230.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-7FED858B-191C-482F-9D6D-C036F45AF5D4" id="BPMNShape_sid-7FED858B-191C-482F-9D6D-C036F45AF5D4">
        <omgdc:Bounds height="40.0" width="40.0" x="509.5" y="251.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-4957D55D-ADC6-487B-90D9-624F05C8A701" id="BPMNShape_sid-4957D55D-ADC6-487B-90D9-624F05C8A701">
        <omgdc:Bounds height="80.0" width="100.0" x="585.0" y="30.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-2E0ED4DF-906A-462E-9870-CEE680EF5850" id="BPMNShape_sid-2E0ED4DF-906A-462E-9870-CEE680EF5850">
        <omgdc:Bounds height="80.0" width="100.0" x="600.0" y="231.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-80018531-8ED9-465D-98BB-FA2099D7FF53" id="BPMNShape_sid-80018531-8ED9-465D-98BB-FA2099D7FF53">
        <omgdc:Bounds height="80.0" width="100.0" x="585.0" y="435.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-4BEB0469-13B5-431C-BAA1-A7B287F87466" id="BPMNShape_sid-4BEB0469-13B5-431C-BAA1-A7B287F87466">
        <omgdc:Bounds height="40.0" width="40.0" x="865.5" y="240.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-147019FA-10BA-4515-9C48-0DC8EABCE4A3" id="BPMNShape_sid-147019FA-10BA-4515-9C48-0DC8EABCE4A3">
        <omgdc:Bounds height="80.0" width="100.0" x="950.5" y="220.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-917A8382-52D5-4FAD-B63E-7128AF17642D" id="BPMNShape_sid-917A8382-52D5-4FAD-B63E-7128AF17642D">
        <omgdc:Bounds height="28.0" width="28.0" x="1095.5" y="246.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-7A5207E3-A904-4A98-9C3A-9900907194D3" id="BPMNEdge_sid-7A5207E3-A904-4A98-9C3A-9900907194D3">
        <omgdi:waypoint x="339.94999999998737" y="270.2085594989561"></omgdi:waypoint>
        <omgdi:waypoint x="509.5377182044852" y="270.9168399168399"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-9738C454-8C67-40F5-A476-AB4B21002BD5" id="BPMNEdge_sid-9738C454-8C67-40F5-A476-AB4B21002BD5">
        <omgdi:waypoint x="684.9499999999999" y="107.88622754491014"></omgdi:waypoint>
        <omgdi:waypoint x="874.120006808897" y="251.37343927355278"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-2FFD0B50-091B-4F52-8CE0-F59B43022217" id="BPMNEdge_sid-2FFD0B50-091B-4F52-8CE0-F59B43022217">
        <omgdi:waypoint x="530.0" y="290.4453462671906"></omgdi:waypoint>
        <omgdi:waypoint x="530.0" y="475.0"></omgdi:waypoint>
        <omgdi:waypoint x="585.0" y="475.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-08FC379C-107A-4867-ACC7-C7DD7F6ADFA0" id="BPMNEdge_sid-08FC379C-107A-4867-ACC7-C7DD7F6ADFA0">
        <omgdi:waypoint x="104.94999954302153" y="270.0"></omgdi:waypoint>
        <omgdi:waypoint x="240.0" y="270.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-1B7BF3D8-5D8B-43F3-B506-552851D59500" id="BPMNEdge_sid-1B7BF3D8-5D8B-43F3-B506-552851D59500">
        <omgdi:waypoint x="681.5463953488372" y="435.0"></omgdi:waypoint>
        <omgdi:waypoint x="874.7373791621912" y="269.2142857142857"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-E0E06131-6A7A-41E5-BC68-632698AF1EF3" id="BPMNEdge_sid-E0E06131-6A7A-41E5-BC68-632698AF1EF3">
        <omgdi:waypoint x="549.0213001672096" y="271.4205020920502"></omgdi:waypoint>
        <omgdi:waypoint x="600.0" y="271.208125"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-E5600212-5D8F-4367-9DCD-5CDCD302DB36" id="BPMNEdge_sid-E5600212-5D8F-4367-9DCD-5CDCD302DB36">
        <omgdi:waypoint x="905.0247370727432" y="260.4166666666667"></omgdi:waypoint>
        <omgdi:waypoint x="950.4999999999881" y="260.2181222707424"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-7FB255C5-72F9-401A-B87D-5BBAFCA32607" id="BPMNEdge_sid-7FB255C5-72F9-401A-B87D-5BBAFCA32607">
        <omgdi:waypoint x="699.9499999999999" y="268.6645435244161"></omgdi:waypoint>
        <omgdi:waypoint x="866.3924949290059" y="260.8902636916835"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-0247BC34-F747-4072-B43C-D9A2A9C819CB" id="BPMNEdge_sid-0247BC34-F747-4072-B43C-D9A2A9C819CB">
        <omgdi:waypoint x="1050.45" y="260.0"></omgdi:waypoint>
        <omgdi:waypoint x="1095.5" y="260.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-739AC77C-B5D2-47D4-9B46-B5187B30F257" id="BPMNEdge_sid-739AC77C-B5D2-47D4-9B46-B5187B30F257">
        <omgdi:waypoint x="530.0" y="251.5"></omgdi:waypoint>
        <omgdi:waypoint x="530.0" y="70.0"></omgdi:waypoint>
        <omgdi:waypoint x="585.0" y="70.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

1.3流程部署 和 启动流程

部署流程:

@Test
public void DeployProcess(){
    Deployment holiday = repositoryService.createDeployment()
            .addClasspathResource("包容网关.bpmn20.xml")
            .name("包容网关")
            .deploy();
}

启动流程:

@Test
public void StatrProcess(){
    //先查到流程
    ProcessDefinition leave_key = repositoryService.createProcessDefinitionQuery().processDefinitionKey("Inclusive_gateway").singleResult();
    //启动流程并分配给
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(leave_key.getId());
}

可以从DB中看到任务已经启动下面我们使用zhangsan完成下任务

image.png

1.4 使用 zhangsan 完成任务

注意我们这里的num 是6 也就是说 任务表中会出现 人事审批经理审批

@Test
public void comleteProcess(){
    Task task = taskService.createTaskQuery()
            //ACT_RU_TASK 表中 PROC_INST_ID_
            .processInstanceId("cd6401f3-e4a6-11ec-9d53-666ee0fc370d")
            .taskAssignee("zhangsan")
            .singleResult();
    if (task!=null){
        Map<String,Object> map=new HashMap<>();
        map.put("num",6);
        taskService.complete(task.getId(),map);
        System.out.println("完成");
        //去 历史表中查看
    }
}

DB任务表中可以查看到 人事审批经理审批这两个任务并行了。

image.png

1.5 下面我们把 人事审批经理审批 这两个任务完成下

就不一一 贴了,换一个执行人把他们两的任务完成。

@Test
public void comleteProcess(){
    Task task = taskService.createTaskQuery()
            //ACT_RU_TASK 表中 PROC_INST_ID_
            .processInstanceId("cd6401f3-e4a6-11ec-9d53-666ee0fc370d")
            .taskAssignee("zz")//wangwu
            .singleResult();
    if (task!=null){
        taskService.complete(task.getId());
        System.out.println("完成");
        //去 历史表中查看
    }
}

完成这两个任务就流转到了 财务审批

image.png

1.6 最后就是 完成财务审批 结束流程流转

完成财务审批:

@Test
public void comleteProcess(){
    Task task = taskService.createTaskQuery()
            //ACT_RU_TASK 表中 PROC_INST_ID_
            .processInstanceId("cd6401f3-e4a6-11ec-9d53-666ee0fc370d")
            .taskAssignee("mon")//
            .singleResult();
    if (task!=null){
        taskService.complete(task.getId());
        System.out.println("完成");
        //去 历史表中查看
    }
}

DB历史数据中查看流程信息

image.png 可以理解为:包含网关就是 排他网关和并行网关的 结合体

2.事件网关

2.1什么是事件网关

基于事件的网关event-based gateway提供了根据事件做选择的方式。网关的每一条出口顺序流都需要连接至一个捕获中间事件。当流程执行到达基于事件的网关时,与等待状态类似,网关会暂停执行,并且为每一条出口顺序流创建一个事件订阅。
注意:基于事件的网关的出口顺序流与一般的顺序流不同。这些顺序流从不实际执行。相反,它们用于告知流程引擎:当执行到达一个基于事件的网关时,需要订阅什么事件。有以下限制:

  • 一个基于事件的网关,必须有两条或更多的出口顺序流。
  • 基于事件的网关,只能连接至intermediateCatchEvent(捕获中间事件)类型的元素(Flowable不支持在基于事件的网关之后连接“接收任务 Receive Task”)。
  • 连接至基于事件的网关的intermediateCatchEvent,必须只有一个入口顺序流。

2.2 流程图和XML 文件

流程图:

image.png XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:flowable="http://flowable.org/bpmn"
             targetNamespace="Examples">

  <signal id="alertSignal" name="alert" />

  <process id="catchSignal">

    <startEvent id="start" />

    <sequenceFlow sourceRef="start" targetRef="gw1" />

    <eventBasedGateway id="gw1" />

    <sequenceFlow sourceRef="gw1" targetRef="signalEvent" />
    <sequenceFlow sourceRef="gw1" targetRef="timerEvent" />

    <intermediateCatchEvent id="signalEvent" name="Alert">
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateCatchEvent>

    <intermediateCatchEvent id="timerEvent" name="Alert">
      <timerEventDefinition>
        <timeDuration>PT2M</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>

    <sequenceFlow sourceRef="timerEvent" targetRef="exGw1" />
    <sequenceFlow sourceRef="signalEvent" targetRef="task" />

    <userTask id="task" name="测试"/>

    <exclusiveGateway id="exGw1" />

    <sequenceFlow sourceRef="task" targetRef="exGw1" />
    <sequenceFlow sourceRef="exGw1" targetRef="end" />

    <endEvent id="end" />
  </process>
</definitions>

这个流程图的意思是 2分钟之内 如果没有 信号事件触发的话直接结束,两分钟之类信号触发的话 ,则会取消定时器,流程沿着信号继续执行走触发之后的流程 走到测试

2.3 部署 和 启动 流程

部署流程:

@Test
public void DeployProcess(){
    Deployment holiday = repositoryService.createDeployment()
            .addClasspathResource("事件网关.bpmn20.xml")
            .name("事件网关")
            .deploy();
}

启动流程:

@Test
public void StatrProcess(){
    //先查到流程
    ProcessDefinition leave_key = repositoryService.createProcessDefinitionQuery().processDefinitionKey("event_gateway").singleResult();
    //启动流程并分配给
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(leave_key.getId());
}

在 DB ACT_RU_TIMER_JOB 表中可以看到创建的定时任务 image.png

2.4 触发信号

测试:

@Test
public void send(){
    runtimeService.signalEventReceived("alert");
}

可以看到信号任务创建了,按照信号这边流程执行了 image.png

2.5 完成下流程

@Test
public void comleteProcess(){
    Task task = taskService.createTaskQuery()
            //ACT_RU_TASK 表中 PROC_INST_ID_
            .processInstanceId("39cc1769-e4b6-11ec-96b3-666ee0fc370d")
            .singleResult();
    if (task!=null){
        Map<String,Object> map=new HashMap<>();
        map.put("status","true");
        taskService.complete(task.getId(),map);
        System.out.println("完成");
        //去 历史表中查看
    }
}

在历史数据中查看结束的流程 image.png

2.6 如果一直不释放信号

如果信号在2分钟内触发,则会取消定时器,流程沿着信号继续执行,激活测试用户任务。如果2分钟内没有触发信号,则会继续执行,并取消信号订阅。 image.png 任务表:

image.png 还有很多事件这里就不一一演示了
实践是检验真理的唯一方法! 明天见🥰🥰🥰