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 &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 &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 &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 &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 &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
事件 = 等谁先发生(只能连捕获)