返回介绍

8.4. 网关

发布于 2023-09-17 23:40:35 字数 9988 浏览 0 评论 0 收藏 0

网关(gateway)用于控制执行的流向(或者按BPMN 2.0的用词:执行的“标志(token)”)。网关可以消费(consuming)生成(generating)标志。

网关用其中带有图标的菱形表示。该图标显示了网关的类型。

bpmn.gateway

8.4.1. 排他网关

描述

排他网关(exclusive gateway)(也叫异或网关 XOR gateway,或者更专业的,基于数据的排他网关 exclusive data-based gateway),用于对流程中的决策建模。当执行到达这个网关时,会按照所有出口顺序流定义的顺序对它们进行计算。选择第一个条件计算为true的顺序流(当没有设置条件时,认为顺序流为true)继续流程。

请注意这里出口顺序流的含义与BPMN 2.0中的一般情况不一样。一般情况下,会选择所有条件计算为true的顺序流,并行执行。而使用排他网关时,只会选择一条顺序流。当多条顺序流的条件都计算为true时,会且仅会选择在XML中最先定义的顺序流继续流程。如果没有可选的顺序流,会抛出异常。

图示

排他网关用内部带有’X’图标的标准网关(菱形)表示,'X’图标代表异或的含义。请注意内部没有图标的网关默认为排他网关。BPMN 2.0规范不允许在同一个流程中混合使用有及没有X的菱形标志。

bpmn.exclusive.gateway.notation

XML表示

排他网关的XML表示格式很简洁:一行定义网关的XML。条件表达式定义在其出口顺序流上。查看条件顺序流章节了解这种表达式的可用选项。

以下面的模型为例:

bpmn.exclusive.gateway

其XML表示如下:

<exclusiveGateway name="Exclusive Gateway" />

<sequenceFlow sourceRef="exclusiveGw" targetRef="theTask1">
  <conditionExpression xsi:type="tFormalExpression">${input == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow sourceRef="exclusiveGw" targetRef="theTask2">
  <conditionExpression xsi:type="tFormalExpression">${input == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow sourceRef="exclusiveGw" targetRef="theTask3">
  <conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression>
</sequenceFlow>

8.4.2. 并行网关

描述

网关也可以建模流程中的并行执行。在流程模型中引入并行的最简单的网关,就是并行网关(parallel gateway)。它可以将执行分支(fork)为多条路径,也可以合并(join)多条入口路径的执行。

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

  • 分支:所有的出口顺序流都并行执行,为每一条顺序流创建一个并行执行。

  • 合并:所有到达并行网关的并行执行都会在网关处等待,直到每一条入口顺序流都到达了有个执行。然后流程经过该合并网关继续。

请注意,如果并行网关同时具有多条入口与出口顺序流,可以同时具有分支与合并的行为。在这种情况下,网关首先合并所有入口顺序流,然后分裂为多条并行执行路径。

与其他网关类型有一个重要区别:并行网关不计算条件。如果连接到并行网关的顺序流上定义了条件,会直接忽略该条件。

图示

并行网关,用内部带有’加号’图标的网关(菱形)表示,代表与(AND)的含义。

bpmn.parallel.gateway

XML表示

定义并行网关只需要一行XML:

<parallelGateway />

实际行为(分支,合并或两者皆有),由连接到该并行网关的顺序流定义。

例如,上面的模型表示为下面的XML:

<startEvent />
<sequenceFlow sourceRef="theStart" targetRef="fork" />

<parallelGateway />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />

<userTask name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<parallelGateway />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent />

在上面的例子中,当流程启动后会创建两个任务:

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");
TaskQuery query = taskService.createTaskQuery()
  .processInstanceId(pi.getId())
  .orderByTaskName()
  .asc();

List<Task> tasks = query.list();
assertEquals(2, tasks.size());

Task task1 = tasks.get(0);
assertEquals("Receive Payment", task1.getName());
Task task2 = tasks.get(1);
assertEquals("Ship Order", task2.getName());

当这两个任务完成后,第二个并行网关会合并这两个执行。由于它只有一条出口顺序流,因此就不会再创建并行执行路径,而只是激活Archive Order(存档订单)任务。

请注意并行网关不需要“平衡”(也就是说,前后对应的两个并行网关,其入口/出口顺序流的数量不需要一致)。每个并行网关都会简单地等待所有入口顺序流,并为每一条出口顺序流创建并行执行,而不受流程模型中的其他结构影响。因此,下面的流程在BPMN 2.0中是合法的:

bpmn.unbalanced.parallel.gateway

8.4.3. 包容网关

描述

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

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

  • 分支:流程会计算所有出口顺序流的条件。对于每一条计算为true的顺序流,流程都会创建一个并行执行。

  • 合并:所有到达包容网关的并行执行,都会在网关处等待。直到每一条具有流程标志(process token)的入口顺序流,都有一个执行到达。这是与并行网关的重要区别。换句话说,包容网关只会等待可以被执行的入口顺序流。在合并后,流程穿过合并并行网关继续。

请注意,如果包容网关同时具有多条入口与出口顺序流,可以同时具有分支与合并的行为。在这种情况下,网关首先合并所有具有流程标志的入口顺序流,然后为每一个条件计算为true的出口顺序流分裂出并行执行路径。

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

— 译者附(翻译自alfresco文档 http://docs.alfresco.com/process-services1.6/topics/inclusive_gateway.html)

图示

包容网关,用内部带有’圆圈’图标的网关(菱形)表示。

bpmn.inclusive.gateway

XML表示

定义包容网关需要一行XML:

<inclusiveGateway />

实际行为(分支,合并或两者皆有),由连接到该包容网关的顺序流定义。

例如,上面的模型表现为下面的XML:

<startEvent />
<sequenceFlow sourceRef="theStart" targetRef="fork" />

<inclusiveGateway />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" >
  <conditionExpression xsi:type="tFormalExpression">${paymentReceived == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="fork" targetRef="shipOrder" >
  <conditionExpression xsi:type="tFormalExpression">${shipOrder == true}</conditionExpression>
</sequenceFlow>

<userTask name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<inclusiveGateway />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent />

在上面的例子中,当流程启动后,如果流程变量paymentReceived == false且shipOrder == true,会创建两个任务。如果只有一个流程变量等于true,则只会创建一个任务。如果没有条件计算为true,会抛出异常(可通过指定默出口顺序流避免)。在下面的例子中,只会创建ship order(传递订单)一个任务:

HashMap<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("receivedPayment", true);
variableMap.put("shipOrder", true);

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");

TaskQuery query = taskService.createTaskQuery()
  .processInstanceId(pi.getId())
  .orderByTaskName()
  .asc();

List<Task> tasks = query.list();
assertEquals(1, tasks.size());

Task task = tasks.get(0);
assertEquals("Ship Order", task.getName());

当这个任务完成后,第二个包容网关会合并这两个执行。并且由于它只有一条出口顺序流,所有不会再创建并行执行路径,而只会激活Archive Order(存档订单)任务。

请注意包容网关不需要“平衡”(也就是说,对应的包容网关,其入口/出口顺序流的数量不需要匹配)。包容网关会简单地等待所有入口顺序流,并为每一条出口顺序流创建并行执行,不受流程模型中的其他结构影响。

请注意包容网关不需要“平衡”(也就是说,前后对应的两个包容网关,其入口/出口顺序流的数量不需要一致)。每个包容网关都会简单地等待所有入口顺序流,并为每一条出口顺序流创建并行执行,不受流程模型中的其他结构影响。

8.4.4. 基于事件的网关

描述

基于事件的网关(event-based gateway)提供了根据事件做选择的方式。网关的每一条出口顺序流都需要连接至一个捕获中间事件。当流程执行到达基于事件的网关时,与等待状态类似,网关会暂停执行,并且为每一条出口顺序流创建一个事件订阅。

请注意:基于事件的网关的出口顺序流与一般的顺序流不同。这些顺序流从不实际执行。相反,它们用于告知流程引擎:当执行到达一个基于事件的网关时,需要订阅什么事件。有以下限制:

  • 一个基于事件的网关,必须有两条或更多的出口顺序流。

  • 基于事件的网关,只能连接至intermediateCatchEvent(捕获中间事件)类型的元素(Flowable不支持在基于事件的网关之后连接“接收任务 Receive Task”)。

  • 连接至基于事件的网关的intermediateCatchEvent,必须只有一个入口顺序流。

图示

基于事件的网关,用内部带有特殊图标的网关(菱形)表示。

bpmn.event.based.gateway.notation

XML表示

用于定义基于事件的网关的XML元素为eventBasedGateway

示例

下面是一个带有基于事件的网关的示例流程。当执行到达基于事件的网关时,流程执行暂停。流程实例订阅alert信号事件,并创建一个10分钟后触发的定时器。流程引擎会等待10分钟,并同时等待信号事件。如果信号在10分钟内触发,则会取消定时器,流程沿着信号继续执行,激活Handle alert用户任务。如果10分钟内没有触发信号,则会继续执行,并取消信号订阅。

bpmn.event.based.gateway.example
<definitions
	xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
	xmlns:flowable="http://flowable.org/bpmn"
	targetNamespace="Examples">

  <signal name="alert" />

  <process>

    <startEvent />

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

    <eventBasedGateway />

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

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

    <intermediateCatchEvent name="Alert">
      <timerEventDefinition>
        <timeDuration>PT10M</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>

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

    <userTask name="Handle alert"/>

    <exclusiveGateway />

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

    <endEvent />
  </process>
</definitions>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文