如何控制工作流中的流程流转?工作流流程元素之顺序流和网关的详细解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 本文详细说明了工作流中实现流程流转的两种实现方式,分别是顺序流和网关。顺序流包括条件顺序流和默认使用的顺序流。网关包括排他网关,并行网关,包含网关以及基于事件的网关。通过对顺序流和网关的学习,可以熟练的掌握了工作流Activiti框架中最核心的点,也就是流程的流转。

顺序流

描述
  • 顺序流是连接两个流程节点的连线
  • 流程执行完一个节点后,会沿着节点的所有外出顺序流继续执行
  • BPMN 2.0默认的行为就是并发的:两个外出顺序流会创造两个单独的,并发流程分支
图形标记
  • 顺序流显示为从起点到终点的箭头.箭头总是指向终点

在这里插入图片描述

XML内容
  • 顺序流需要流程范围内唯一的id, 以及对起点终点元素的引用
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />

条件顺序流

描述
  • 为顺序流定义一个条件
  • 离开一个BPMN 2.0节点时,默认会计算外出顺序流的条件

    • 如果条件结果为true,就会选择外出顺序流继续执行
    • 当多条顺序流被选中时,就会创建多条分支,流程会继续以并行方式继续执行
  • ==注意:== 不包括网关 ,网关会用特定的方式处理顺序流中的条件, 这与网关类型相关
图形标记
  • 条件顺序流显示为一个正常的顺序流,在起点有一个菱形. 条件表达式也会显示在顺序流上

在这里插入图片描述

XML内容
  • 条件顺序流定义为一个正常的顺序流, 包含conditionExpression子元素
  • 目前只支持tFormalExpressions, 如果没有设置xsi:type="", 就会默认值支持目前支持的表达式类型
<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask">
  <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${order.price > 100 && order.price < 250}]]>
  </conditionExpression>
</sequenceFlow>
  • 当前条件表达式只能使用UEL, 使用的表达式需要返回boolean值,否则会在解析表达式时抛出异常

    • 引用了流程变量的数据,通过getter调用JavaBean

      <conditionExpression xsi:type="tFormalExpression">
      <![CDATA[${order.price > 100 && order.price < 250}]]>
      </conditionExpression>
      • 通过调用方法返回一个boolean值

        <conditionExpression xsi:type="tFormalExpression">
        <![CDATA[${order.isStandardOrder()}]]>
        </conditionExpression>
  • 在activiti发布包中,包含以下流程实例,使用了值和方法表达式

在这里插入图片描述

默认顺序流

描述
  • 所有的BPMN 2.0任务和网关都可以设置一个默认顺序流
  • 只有在节点的其它外出顺序流不能被选中时,才会使用作为外出顺序流继续执行
  • 默认顺序流的条件设置不会生效
图形标记
  • 默认顺序流显示为普通顺序流, 起点有一个斜线标记

在这里插入图片描述

XML内容
  • 默认顺序流通过对应节点的default属性定义
  • 下面的XML代码演示了排他网关设置了默认顺序流flow 2.只有当conditionA和conditionB都返回false时,才会选择它作为外出连线继续执行:
<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow2" />
<sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">
  <conditionExpression xsi:type="tFormalExpression">${conditionA}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/>
<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3">
  <conditionExpression xsi:type="tFormalExpression">${conditionB}</conditionExpression>
</sequenceFlow>
  • 对应图形:

在这里插入图片描述

网关

  • 网关用来控制流程的流向(流程的tokens),网关可以消费也可以生成token
  • 网关显示成菱形图形,内部有有一个小图标.图标表示网关的类型:

在这里插入图片描述

排他网关

描述
  • 排他网关: 异或XOR网关,用来在流程中实现决策
  • 当流程执行到这个网关,所有外出顺序流都会被处理一遍.其中条件解析为true的顺序流(或者没有设置条件,概念上在顺序流上定义了一个[true])会被选中,让流程继续运行
  • ==注意:== 通常情况下,所有条件结果为true的顺序流都会被选中,以并行方式执行,但排他网关只会选择一条顺序流执行. 就是说,虽然多个顺序流的条件结果为true,那么XML中的第一个顺序流(也只有这一条)会被选中,并用来继续运行流程.如果没有选中任何顺序流,会抛出一个异常
图形标记
  • 排他网关显示成一个普通网关(比如,菱形图形),内部是一个X图标,表示异或(XOR)语义.
  • 没有内部图标的网关,默认为排他网关
  • BPMN 2.0规范不允许在同一个流程定义中同时使用没有X和有X的菱形图形

在这里插入图片描述

XML内容
  • 用一行定义了网关,条件表达式定义在外出顺序流中
  • 模型实例:

在这里插入图片描述

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />

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

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

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

并行网关

描述
  • 网关也可以表示流程中的并行情况
  • 允许将流程分成多条分支,也可以把多条分支汇聚到一起
  • 并行网关的功能是基于进入和外出的顺序流的:

    • 分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支
    • 汇聚: 所有到达并行网关,在此等待的进入分支 ,直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关
  • 同一个并行网关有多个进入和多个外出顺序流,同时具有分支和汇聚功能
  • 网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支
  • 并行网关不会解析条件: 与其他网关不同,即使顺序流中定义了条件,也会忽略
图形标记
  • 并行网关显示成一个普通网关(菱形)内部是一个 + 图标,表示与(AND) 语义

-

XML内容
  • 定义并行网关只需要一行XML
<parallelGateway id="myParallelGateway" />
  • 实际发生的行为(分支,聚合,同时分支聚合),要根据并行网关的顺序流来决定
 <startEvent id="theStart" />
    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

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

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

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

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

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

    <endEvent id="theEnd" />
  • 流程启动之后,会创建两个任务:
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());

当两个任务都完成时,第二个并行网关会汇聚两个分支.因为它只有一条外出连线,不会创建并行分支,只会创建归档订单任务

  • 注意并行网关不需要是"平衡的"(对应并行网关的进入和外出节点数目相等).并行网关只是等待所有进入顺序流,并为每个外出顺序流创建并发分支,不会受到其他流程节点的影响

在这里插入图片描述

包含网关

描述
  • 排他网关和并行网关的结合体:

    • 和排他网关一样,可以在外出顺序流上定义条件,包含网关会解析条件
    • 和并行网关一样,包含网关可以选择多于一条顺序流
  • 包含网关的功能是基于进入和外出顺序流的:

    • 分支: 所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行方式继续执行,会为每个顺序流创建一个分支
    • 汇聚: 所有并行分支到达包含网关,会进入等待状态,直到每个包含流程token的进入顺序流的分支都到达.这是与并行网关的最大不同.包含网关只会等待被选中执行了的进入顺序流. 在汇聚之后,流程会穿过包含网关继续执行
  • 如果同一个包含节点拥有多个进入和外出顺序流,它就会同时含有分支和汇聚功能
  • 网关会先汇聚所有拥有流程token的进入顺序流,再根据条件判断结果为true的外出顺序流,为它们生成多条并行分支
图形标记
  • 并行网关显示为一个普通网关(菱形),内部包含一个圆圈图标

在这里插入图片描述

XML内容
  • 定义一个包含网关需要一行XML
<inclusiveGateway id="myInclusiveGateway" />
  • 实际的行为(分支,汇聚,同时分支汇聚),是由连接在包含网关的顺序流决定的
 <startEvent id="theStart" />
    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

    <inclusiveGateway id="fork" />
    <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 id="receivePayment" name="Receive Payment" />
    <sequenceFlow sourceRef="receivePayment" targetRef="join" />

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

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

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

    <endEvent id="theEnd" />
  • 流程开始之后

    • 如果流程变量为paymentReceived== falseshipOrder == true, 就会创建两个任务
    • 如果只有一个流程变量为true,就会只创建一个任务
    • 如果没有条件为true,就会抛出一个异常
    • 如果想避免异常,可以定义一个默认顺序流
  • 包含网关示例: 创建一个发货任务
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());
  • 当任务完成后,第二个包含网关会汇聚两个分支,因为只有一个外出顺序流,所以不会创建并行分支,只有归档订单任务会被激活
  • 包含网关不需要平衡(对应包含网关的进入和外出数目需要相等).包含网关会等待所有进入顺序流完成,并为每个外出顺序流创建并行分支,不会受到流程中其他元素的影响

基于事件网关

描述
  • 基于事件网关允许根据事件判断流向

    • 网关的每个外出顺序流都要连接到一个中间捕获事件
    • 当流程到达一个基于事件网关 ,网关会进入等待状态:会暂停执行
    • 为每个外出顺序流创建相应的事件订阅
  • 基于事件网关的外出顺序流和普通顺序流不同:这些顺序流不会真的"执行", 让流程引擎去决定执行到基于事件网关的流程需要订阅哪些事件,要考虑以下条件:

    • 基于事件网关必须有两条或以上外出顺序流
    • 基于事件网关后,只能使用intermediateCatchEvent类型(activiti不支持基于事件网关后连接ReceiveTask)
    • 连接到基于事件网关的intermediateCatchEvent只能有一条进入顺序流
图形标记
  • 基于事件网关和其他BPMN网关一样显示成一个菱形,内部包含指定图标

在这里插入图片描述

XML内容
  • 用来定义基于事件网关的XML元素是eventBasedGateway
实例
  • 基于事件网关示例:

    • 当流程执行到基于事件网关时,流程会暂停执行
    • 与此同时,流程实例会订阅警告信号事件,并创建一个10分钟后触发的定时器.产生流程引擎为一个信号事件等待10分钟的效果
    • 如果10分钟内发出信号,定时器就会取消,流程会沿着信号执行
    • 如果信号没有出现,流程会沿着定时器的方向前进,信号订阅会被取消

    -

<definitions id="definitions"
        xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:activiti="http://activiti.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>PT10M</timeDuration>
                        </timerEventDefinition>
                </intermediateCatchEvent>

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

                <userTask id="task" name="Handle alert"/>

                <exclusiveGateway id="exGw1" />

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

                <endEvent id="end" />
</process>
</definitions>
相关文章
|
29天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
38 3
|
1月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
41 3
|
9天前
|
域名解析 网络协议 测试技术
IP、掩码、网关、DNS1、DNS2到底是什么东西,ping telnet测试
理解IP地址、子网掩码、默认网关和DNS服务器的概念是有效管理和配置网络的基础。通过使用ping和telnet命令,可以测试网络连通性和服务状态,快速诊断和解决网络问题。这些工具和概念是网络管理员和IT专业人员日常工作中不可或缺的部分。希望本文提供的详细解释和示例能够帮助您更好地理解和应用这些网络配置和测试工具。
29 2
|
1月前
|
JavaScript 前端开发 UED
Vue执行流程及渲染解析
【10月更文挑战第5天】
|
1月前
|
存储 搜索推荐 数据库
运用LangChain赋能企业规章制度制定:深入解析Retrieval-Augmented Generation(RAG)技术如何革新内部管理文件起草流程,实现高效合规与个性化定制的完美结合——实战指南与代码示例全面呈现
【10月更文挑战第3天】构建公司规章制度时,需融合业务实际与管理理论,制定合规且促发展的规则体系。尤其在数字化转型背景下,利用LangChain框架中的RAG技术,可提升规章制定效率与质量。通过Chroma向量数据库存储规章制度文本,并使用OpenAI Embeddings处理文本向量化,将现有文档转换后插入数据库。基于此,构建RAG生成器,根据输入问题检索信息并生成规章制度草案,加快更新速度并确保内容准确,灵活应对法律与业务变化,提高管理效率。此方法结合了先进的人工智能技术,展现了未来规章制度制定的新方向。
34 3
|
1月前
|
存储 缓存 边缘计算
揭秘直播带货背后的黑科技:播放流程全解析!
大家好,我是小米,今天聊聊社区直播带货的技术细节。我们将探讨直播播放流程中的关键技术,包括 HTTP DASH 协议、POP(Point of Presence)缓存和一致性哈希算法等。通过这些技术,直播流能根据网络状况动态调整清晰度,保证流畅体验。POP 和 DC 的多层次缓存设计减少了延迟,提升了观看效果。无论是技术人员还是直播运营者,都能从中受益。希望通过本文,你能更好地理解直播背后的技术原理。
46 3
|
1月前
|
弹性计算 网络协议 网络安全
内网DNS解析&VPN网关联动实现云上访问云下资源
内网DNS解析&VPN网关联动实现云上访问云下资源
|
1月前
|
敏捷开发 数据可视化 测试技术
解析软件项目管理:以板栗看板为例,其如何有效影响并优化软件开发流程
软件项目管理是一个复杂而重要的过程,涵盖了软件产品的创建、维护和优化。其核心目标是确保软件项目能够顺利完成,同时满足预定的质量、时间和预算目标。本文将深入探讨软件项目管理的内涵及其对软件开发过程的影响,并介绍一些有效的管理工具。
|
5天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
19 2
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
67 0

推荐镜像

更多