【flowable专栏】网关类型

1.排他网关(Exclusive Gateway)

这个可以说是我们最最最常用的一个网关了,实际上可以理解为if-else。

常见场景:金额报销

注意:条件可以有多个,但是为true的情况必须要有且只能有一个,否则会报错。

建议:添加一个默认的路径,防止全false的情况。

例子:

xml 复制代码
<process id="flow_fxbn4kjb" name="flow_mdrr27se">
    <startEvent id="start_event" name="开始">
      <outgoing>Flow_0dso2ii</outgoing>
    </startEvent>
    <userTask id="Activity_1b7dkwh" name="审批人A">
      <incoming>Flow_0dso2ii</incoming>
      <outgoing>Flow_1h46vbf</outgoing>
    </userTask>
    <sequenceFlow id="Flow_0dso2ii" sourceRef="start_event" targetRef="Activity_1b7dkwh" />
    <exclusiveGateway id="Gateway_0gs8sp7" name="排斥网关">
      <incoming>Flow_1h46vbf</incoming>
      <outgoing>Flow_09abes7</outgoing>
      <outgoing>Flow_0xb14rh</outgoing>
    </exclusiveGateway>
    <sequenceFlow id="Flow_1h46vbf" sourceRef="Activity_1b7dkwh" targetRef="Gateway_0gs8sp7" />
    <userTask id="Activity_1ugsmv9" name="审核人B">
      <incoming>Flow_09abes7</incoming>
      <outgoing>Flow_0guuy54</outgoing>
    </userTask>
    <sequenceFlow id="Flow_09abes7" sourceRef="Gateway_0gs8sp7" targetRef="Activity_1ugsmv9">
      <conditionExpression xsi:type="tFormalExpression">${amount &amp;lt; 1000}</conditionExpression>
    </sequenceFlow>
    <userTask id="Activity_1g0kati" name="审核人C">
      <incoming>Flow_0xb14rh</incoming>
      <outgoing>Flow_17yxqht</outgoing>
    </userTask>
    <sequenceFlow id="Flow_0xb14rh" sourceRef="Gateway_0gs8sp7" targetRef="Activity_1g0kati">
      <conditionExpression xsi:type="tFormalExpression">${amount &amp;gt;= 1000}</conditionExpression>
    </sequenceFlow>
    <endEvent id="Event_00bedoo" name="结束">
      <incoming>Flow_0guuy54</incoming>
      <incoming>Flow_17yxqht</incoming>
    </endEvent>
    <sequenceFlow id="Flow_0guuy54" sourceRef="Activity_1ugsmv9" targetRef="Event_00bedoo" />
    <sequenceFlow id="Flow_17yxqht" sourceRef="Activity_1g0kati" targetRef="Event_00bedoo" />
  </process>

2.并行网关(Parallel Gateway)

简单来说,就是先分叉再相聚,所有路线一起走,最后等待全部到齐再往后走。

ps:不是说一定要有一个分叉和聚合得并行网关,但是更推荐这样。

并行网关机制:内置计数器,等所有分支都到达才放行一次。

下面分几种情况分析:

不用网关,汇聚点是任务节点,会执行多次,按照先后顺序。

排斥网关,无计数器,每条分支到达都判断条件,满足即放行 → 后续可能执行多次。

唯一可用场景:后续节点是无状态通知(发邮件、发短信),重复执行无影响。

包容网关,内置活跃分支计数器,等所有活跃分支到达才放行一次,可模拟并行网关。但 性能略差(包容网关计算更复杂),无实际收益。

事件网关,只能聚合捕获事件,谁先到谁走,其他事件自动失效。

适用场景:B 和 C 谁先完成,就走谁的后续逻辑,互斥,不汇总。

总的来说,最好还是按照规范来,这样才是最好的实现方案。

例子:

xml 复制代码
<process id="flow_fxbn4kjb" name="flow_mdrr27se">
    <startEvent id="start_event" name="开始">
      <outgoing>Flow_0dso2ii</outgoing>
    </startEvent>
    <userTask id="Activity_1b7dkwh" name="审批人A">
      <incoming>Flow_0dso2ii</incoming>
      <outgoing>Flow_1h46vbf</outgoing>
    </userTask>
    <sequenceFlow id="Flow_0dso2ii" sourceRef="start_event" targetRef="Activity_1b7dkwh" />
    <sequenceFlow id="Flow_1h46vbf" sourceRef="Activity_1b7dkwh" targetRef="Gateway_0gs8sp7" />
    <userTask id="Activity_1ugsmv9" name="审核人B">
      <incoming>Flow_09abes7</incoming>
      <outgoing>Flow_1xq7lef</outgoing>
    </userTask>
    <sequenceFlow id="Flow_09abes7" sourceRef="Gateway_0gs8sp7" targetRef="Activity_1ugsmv9" />
    <userTask id="Activity_1g0kati" name="审核人C">
      <incoming>Flow_0xb14rh</incoming>
      <outgoing>Flow_1yb8tzu</outgoing>
    </userTask>
    <sequenceFlow id="Flow_0xb14rh" sourceRef="Gateway_0gs8sp7" targetRef="Activity_1g0kati" />
    <parallelGateway id="Gateway_0gs8sp7" name="并行网关(分叉)">
      <incoming>Flow_1h46vbf</incoming>
      <outgoing>Flow_09abes7</outgoing>
      <outgoing>Flow_0xb14rh</outgoing>
    </parallelGateway>
    <exclusiveGateway id="Gateway_0rgnps9" name="并行网关(聚合)">
      <incoming>Flow_1xq7lef</incoming>
      <incoming>Flow_1yb8tzu</incoming>
      <outgoing>Flow_0ue04bt</outgoing>
    </exclusiveGateway>
    <sequenceFlow id="Flow_1xq7lef" sourceRef="Activity_1ugsmv9" targetRef="Gateway_0rgnps9" />
    <sequenceFlow id="Flow_1yb8tzu" sourceRef="Activity_1g0kati" targetRef="Gateway_0rgnps9" />
    <userTask id="Activity_1bmja5f" name="审批人D">
      <incoming>Flow_0ue04bt</incoming>
      <outgoing>Flow_1mgv6yk</outgoing>
    </userTask>
    <sequenceFlow id="Flow_0ue04bt" sourceRef="Gateway_0rgnps9" targetRef="Activity_1bmja5f" />
    <endEvent id="Event_10q405i" name="结束">
      <incoming>Flow_1mgv6yk</incoming>
    </endEvent>
    <sequenceFlow id="Flow_1mgv6yk" sourceRef="Activity_1bmja5f" targetRef="Event_10q405i" />
  </process>

3.包容网关(Inclusive Gateway)

简单来说,就是符合条件的都一起走,最后等待所有活跃分支聚合再往后走。

ps:聚合网关会自动统计实际走了几条,无需手动维护计数器。

部分代码:

复制代码
    <startEvent id="start_event" name="开始">
      <outgoing>Flow_1v1pr17</outgoing>
    </startEvent>
    <userTask id="Activity_0u17ax3" name="A">
      <incoming>Flow_1v1pr17</incoming>
      <outgoing>Flow_1t6ea6k</outgoing>
    </userTask>
    <sequenceFlow id="Flow_1v1pr17" sourceRef="start_event" targetRef="Activity_0u17ax3" />
    <sequenceFlow id="Flow_1t6ea6k" sourceRef="Activity_0u17ax3" targetRef="Gateway_0dxg1cd" />
    <inclusiveGateway id="Gateway_0dxg1cd" name="包容网关(分叉)">
      <incoming>Flow_1t6ea6k</incoming>
      <outgoing>Flow_1bg6ule</outgoing>
      <outgoing>Flow_1fu8vbk</outgoing>
      <outgoing>Flow_1rtdmr0</outgoing>
    </inclusiveGateway>
    <userTask id="Activity_0pk0yx4" name="B">
      <incoming>Flow_1bg6ule</incoming>
      <outgoing>Flow_03pazic</outgoing>
    </userTask>
    <sequenceFlow id="Flow_1bg6ule" sourceRef="Gateway_0dxg1cd" targetRef="Activity_0pk0yx4">
      <conditionExpression xsi:type="tFormalExpression">${num &amp;gt; 100}</conditionExpression>
    </sequenceFlow>
    <userTask id="Activity_11j4upm" name="C">
      <incoming>Flow_1fu8vbk</incoming>
      <outgoing>Flow_1wa18oz</outgoing>
    </userTask>
    <sequenceFlow id="Flow_1fu8vbk" sourceRef="Gateway_0dxg1cd" targetRef="Activity_11j4upm">
      <conditionExpression xsi:type="tFormalExpression">${num &amp;le; 0}</conditionExpression>
    </sequenceFlow>
    <userTask id="Activity_0578vsx" name="D">
      <incoming>Flow_1rtdmr0</incoming>
      <outgoing>Flow_03k6sdm</outgoing>
    </userTask>
    <sequenceFlow id="Flow_1rtdmr0" sourceRef="Gateway_0dxg1cd" targetRef="Activity_0578vsx">
      <conditionExpression xsi:type="tFormalExpression">${num &amp;lt; 100}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_1wa18oz" sourceRef="Activity_11j4upm" targetRef="Gateway_05le2zp" />
    <inclusiveGateway id="Gateway_05le2zp" name="包容网关(聚合)">
      <incoming>Flow_1wa18oz</incoming>
      <incoming>Flow_03pazic</incoming>
      <incoming>Flow_03k6sdm</incoming>
      <outgoing>Flow_1i51oo7</outgoing>
    </inclusiveGateway>
    <sequenceFlow id="Flow_03pazic" sourceRef="Activity_0pk0yx4" targetRef="Gateway_05le2zp" />
    <sequenceFlow id="Flow_03k6sdm" sourceRef="Activity_0578vsx" targetRef="Gateway_05le2zp" />
    <userTask id="Activity_0jpa4wc" name="E">
      <incoming>Flow_1i51oo7</incoming>
      <outgoing>Flow_1wtf8oo</outgoing>
    </userTask>
    <sequenceFlow id="Flow_1i51oo7" sourceRef="Gateway_05le2zp" targetRef="Activity_0jpa4wc" />
    <endEvent id="Event_1eisxie" name="结束">
      <incoming>Flow_1wtf8oo</incoming>
    </endEvent>
    <sequenceFlow id="Flow_1wtf8oo" sourceRef="Activity_0jpa4wc" targetRef="Event_1eisxie" />
  </process>

4.事件网关(Event-Based Gateway)

简单来说,就是谁先发生就谁生效,其他事件不生效。

注意:

A 事件网关后只能跟捕获事件()

B 一旦某个事件触发,其他事件自动失效

C 不能与 userTask 直连。

部分代码:

xml 复制代码
<process id="orderPayment" name="订单支付处理" isExecutable="true">
    <startEvent id="start"/>
    <sequenceFlow sourceRef="start" targetRef="apply"/>

    <!-- 2. 用户下单 -->
    <userTask id="apply" name="提交订单" flowable:assignee="${userId}"/>
    <sequenceFlow sourceRef="apply" targetRef="eventGate"/>

    <!-- 3. 事件网关:等待第一个发生的事件 -->
    <eventBasedGateway id="eventGate"/>
    <sequenceFlow sourceRef="eventGate" targetRef="waitPayment"/>
    <sequenceFlow sourceRef="eventGate" targetRef="waitTimeout"/>

    <!-- 4. 消息事件:等待支付回调 -->
    <intermediateCatchEvent id="waitPayment" name="等待支付">
      <messageEventDefinition messageRef="msgPaymentSuccess"/>
    </intermediateCatchEvent>
    <sequenceFlow sourceRef="waitPayment" targetRef="confirmPayment"/>
    <serviceTask id="confirmPayment" name="确认支付成功"
                 flowable:delegateExpression="${confirmPaymentDelegate}"/>
    <sequenceFlow sourceRef="confirmPayment" targetRef="end1"/>
    <endEvent id="end1"/>

    <!-- 5. 定时器事件:30分钟超时 -->
    <intermediateCatchEvent id="waitTimeout" name="30分钟超时">
      <timerEventDefinition>
        <timeDuration>PT30M</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>
    <sequenceFlow sourceRef="waitTimeout" targetRef="autoCancel"/>
    <serviceTask id="autoCancel" name="自动取消订单"
                 flowable:delegateExpression="${cancelOrderDelegate}"/>
    <sequenceFlow sourceRef="autoCancel" targetRef="end2"/>
    <endEvent id="end2"/>
  </process>

5.小结

排他 = if-else

并行 = fork-join

包容 = if-else 且 可以多条 true

事件 = 等谁先发生(只能连捕获)

相关推荐
王中阳Go2 小时前
字节开源 Eino 框架上手体验:Go 语言终于有能打的 Agent 编排工具了(含 RAG 实战代码)
人工智能·后端·go
零_守墓人2 小时前
Patroni 中备份恢复和数据迁移
后端
用户1565845925052 小时前
Go技术专家进阶营 从代码开发到架构设计,开启Go技术专家之路
后端
苏近之2 小时前
Rust 中实现定时任务管理
后端·架构·rust
用户8599681677692 小时前
Go技术专家进阶营 从代码开发到架构设计,开启Go技术专家之路
后端
Java水解2 小时前
MySQL定时任务详解 - Event Scheduler 事件调度器从基础到实战
后端·mysql
该用户已不存在2 小时前
7个构建高性能后端的 Rust 必备库
后端·rust
Darenm1112 小时前
JWT鉴权的实现:从原理到 Django + Vue3
后端·python·django
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 基于Springboot的智慧养老系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端