网关和分支是流程图中相当重要的一环。毕竟不可能所有流程都是一条直线走到底的,可能需要并行处理,也可能需要根据条件的不同选择对应的路由,网关的作用正是在此。本文主要探索一下这几种网关的常用方法,以及一些特殊情况会发生什么。由于前面文章中已多次列出流程文档部署、流程启动、提交等代码,本文不再详细列出。

并行网关

并行网关就是当流程到达改网关时,会分成多个分支,对应业务中的并发情况。

假设现在有这么一个场景,公司进行进行项目申报,需要走申报项目流程,待财务部门、采购部门、法律部门审批之后,再到老板审批,最后结束。这过程中财务、采购、合同审批是可以并行处理的。对应的流程图如下:

这里用菱形里面一个“+”的图案表示并行网关,左边的表示分支,右边的表示聚合。我们启动流程之后看看数据库情况。并行网关的“出线”属于无条件走出,即使在“出线”上设置了条件,也不会影响其效果。具体bpmn文档如下:

<?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:activiti="http://activiti.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.activiti.org/test"><process id="并发流程" name="并发流程" isExecutable="true"><startEvent id="startevent1" name="Start"></startEvent><userTask id="申报项目" name="申报项目"></userTask><sequenceFlow id="flow1" sourceRef="startevent1" targetRef="申报项目"></sequenceFlow><parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway><sequenceFlow id="flow2" sourceRef="申报项目" targetRef="parallelgateway1"></sequenceFlow><userTask id="财务审批" name="财务审批"></userTask><userTask id="采购审批" name="采购审批"></userTask><sequenceFlow id="flow4" sourceRef="parallelgateway1" targetRef="采购审批"></sequenceFlow><userTask id="合同审批" name="合同审批"></userTask><sequenceFlow id="flow5" sourceRef="parallelgateway1" targetRef="财务审批"></sequenceFlow><sequenceFlow id="flow6" sourceRef="parallelgateway1" targetRef="合同审批"></sequenceFlow><parallelGateway id="parallelgateway2" name="Parallel Gateway"></parallelGateway><sequenceFlow id="flow7" sourceRef="财务审批" targetRef="parallelgateway2"></sequenceFlow><sequenceFlow id="flow8" sourceRef="采购审批" targetRef="parallelgateway2"></sequenceFlow><sequenceFlow id="flow9" sourceRef="合同审批" targetRef="parallelgateway2"></sequenceFlow><userTask id="老板审批" name="老板审批"></userTask><sequenceFlow id="flow10" sourceRef="parallelgateway2" targetRef="老板审批"></sequenceFlow><endEvent id="endevent1" name="End"></endEvent><sequenceFlow id="flow11" sourceRef="老板审批" targetRef="endevent1"></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_并发流程"><bpmndi:BPMNPlane bpmnElement="并发流程" id="BPMNPlane_并发流程"><bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"><omgdc:Bounds height="35.0" width="35.0" x="200.0" y="190.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="申报项目" id="BPMNShape_申报项目"><omgdc:Bounds height="55.0" width="105.0" x="260.0" y="180.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1"><omgdc:Bounds height="40.0" width="40.0" x="400.0" y="187.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="财务审批" id="BPMNShape_财务审批"><omgdc:Bounds height="55.0" width="105.0" x="485.0" y="110.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="采购审批" id="BPMNShape_采购审批"><omgdc:Bounds height="55.0" width="105.0" x="485.0" y="180.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="合同审批" id="BPMNShape_合同审批"><omgdc:Bounds height="55.0" width="105.0" x="485.0" y="250.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="parallelgateway2" id="BPMNShape_parallelgateway2"><omgdc:Bounds height="40.0" width="40.0" x="630.0" y="187.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="老板审批" id="BPMNShape_老板审批"><omgdc:Bounds height="55.0" width="105.0" x="690.0" y="180.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"><omgdc:Bounds height="35.0" width="35.0" x="840.0" y="190.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="235.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="260.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="365.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="400.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"><omgdi:waypoint x="440.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="485.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"><omgdi:waypoint x="420.0" y="187.0"></omgdi:waypoint><omgdi:waypoint x="420.0" y="137.0"></omgdi:waypoint><omgdi:waypoint x="485.0" y="137.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"><omgdi:waypoint x="420.0" y="227.0"></omgdi:waypoint><omgdi:waypoint x="420.0" y="277.0"></omgdi:waypoint><omgdi:waypoint x="485.0" y="277.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"><omgdi:waypoint x="590.0" y="137.0"></omgdi:waypoint><omgdi:waypoint x="650.0" y="137.0"></omgdi:waypoint><omgdi:waypoint x="650.0" y="187.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8"><omgdi:waypoint x="590.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="630.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9"><omgdi:waypoint x="590.0" y="277.0"></omgdi:waypoint><omgdi:waypoint x="650.0" y="277.0"></omgdi:waypoint><omgdi:waypoint x="650.0" y="227.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10"><omgdi:waypoint x="670.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="690.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11"><omgdi:waypoint x="795.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="840.0" y="207.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

当流程到“申报项目”时

执行表act_ru_execution:

任务表act_ru_task:

这两个表的情况和之前的普通流程没什么不一样。

提交“申报项目”环节到并行分支之后

执行表act_ru_execution:

任务表act_ru_task:

可以看到此时执行表分列成4条记录,其中三条执行分别是采购审批、财务审批、合同审批,还有一条在并行网关处,另外IS_ACTIVE、IS_CONCURRENT、IS_SCOPE有所不同需要注意。而任务表则是三个审批任务。

提交“财务审批”后

执行表act_ru_execution:

任务表act_ru_task:

这时候之前“财务审批”那条execution已经走到了聚合网关,聚合网关正在等待其他的execution。

提交“采购审批”后

执行表act_ru_execution:

任务表act_ru_task:

和上面的执行情况差不多,不需要分析。

提交“合同审批”后

执行表act_ru_execution:

任务表act_ru_task:

当聚合网关的所有“进线”的execution都执行完,就会合并到并行前的execution上,到下一个节点。

并行网关的特点是会使流程从一个execution变成并行的多个execution。通常需要在后面添加聚合网关把并行的execution聚合。如果不加聚合网关,那么流程就会一直维持多个并行execution的状态。

排他网关

当流程执行到排他网关时,排他网关会选择第一条符合条件路由走出。

例如上图,两条“出线”没有设置条件的话,就是默认满足任何条件。此时网关会选择第一条符合的路由。至于哪条是第一条呢?不是由流程图的上下左右方位控制,而是与bpmn文档的顺序有关。因此为了同时符合多个条件时,不知道会走哪条路由的情况,最好还是让路由的条件形成互斥关系。另外,如果流程不满足任意一条“出线”的条件,那么流程就会抛出异常。

现在我们假设一个场景。员工需要走请假申请流程,如果请假小于3天,那么科长审批即可,如果请假大于等于3天,那么需要处长审批。流程图和对应的流程文档大致如下:

<?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:activiti="http://activiti.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.activiti.org/test"><process id="exclusive" name="exclusive" isExecutable="true"><startEvent id="startevent1" name="Start"></startEvent><userTask id="请假申请" name="请假申请"></userTask><sequenceFlow id="flow1" sourceRef="startevent1" targetRef="请假申请"></sequenceFlow><exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway><sequenceFlow id="flow2" sourceRef="请假申请" targetRef="exclusivegateway1"></sequenceFlow><userTask id="处长审批" name="处长审批"></userTask><userTask id="科长审批" name="科长审批"></userTask><sequenceFlow id="flow3" name="day大于等于3天" sourceRef="exclusivegateway1" targetRef="处长审批"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>=3}]]></conditionExpression></sequenceFlow><sequenceFlow id="flow4" name="day小于3天" sourceRef="exclusivegateway1" targetRef="科长审批"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${day<3}]]></conditionExpression></sequenceFlow><endEvent id="endevent1" name="End"></endEvent><sequenceFlow id="flow5" sourceRef="科长审批" targetRef="endevent1"></sequenceFlow><sequenceFlow id="flow6" sourceRef="处长审批" targetRef="endevent1"></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_exclusive"><bpmndi:BPMNPlane bpmnElement="exclusive" id="BPMNPlane_exclusive"><bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"><omgdc:Bounds height="35.0" width="35.0" x="210.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="请假申请" id="BPMNShape_请假申请"><omgdc:Bounds height="55.0" width="105.0" x="290.0" y="160.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1"><omgdc:Bounds height="40.0" width="40.0" x="430.0" y="167.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="处长审批" id="BPMNShape_处长审批"><omgdc:Bounds height="55.0" width="105.0" x="500.0" y="116.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="科长审批" id="BPMNShape_科长审批"><omgdc:Bounds height="55.0" width="105.0" x="500.0" y="207.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"><omgdc:Bounds height="35.0" width="35.0" x="650.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="245.0" y="187.0"></omgdi:waypoint><omgdi:waypoint x="290.0" y="187.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="395.0" y="187.0"></omgdi:waypoint><omgdi:waypoint x="430.0" y="187.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"><omgdi:waypoint x="450.0" y="167.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="143.0"></omgdi:waypoint><omgdi:waypoint x="500.0" y="143.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0" width="100.0" x="410.0" y="131.0"></omgdc:Bounds></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"><omgdi:waypoint x="450.0" y="207.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="234.0"></omgdi:waypoint><omgdi:waypoint x="500.0" y="234.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0" width="100.0" x="390.0" y="239.0"></omgdc:Bounds></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"><omgdi:waypoint x="605.0" y="234.0"></omgdi:waypoint><omgdi:waypoint x="667.0" y="205.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"><omgdi:waypoint x="605.0" y="143.0"></omgdi:waypoint><omgdi:waypoint x="667.0" y="170.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

通过xml写入条件比较麻烦,我们通过eclipse的Activiti Diagram Editor插件进行编辑。这里使用了表达式进行条件设置。

例如这里我们给上面这条“出线”设置day变量大于等于3,下面那条“出线”设置day变量小于3

启动流程,程走到“请假申请”环节

任务表act_ru_task:

之后提交下一个环节前,我们传入day变量,设置为2

public void completeTaskWithVar() {Map<String, Object> vars = new HashMap<String, Object>();vars.put("day", 2);TaskService taskService = pe.getTaskService();taskService.complete("5010", vars);System.out.println("完成提交");
}

流程到排他网关,根据条件选择路由后

任务表act_ru_task:

通过任务表可以看到流程走到了“科长审批”环节。由于day设置为2,通过排他网关两条“出线”的条件判断,走下面那条路由。

包含网关

包含网关融合了并行网关和排他网关的特点,并行网关的“出线”属于无条件,而排他网关只能选择符合条件的第一条“出线”。那如果我们需要一个路由选择,只要满足条件的“出线”,都可以路由走出去,这时候需要选择包含网关。

例如上图,我们设定一个采购申报流程,无论什么情况,都需要采购部领导审批,而如果费用大于等于1万元,则同时需要通过大老板审批。包含网关上面的“出线”没设任何条件,下面的“出线”设置了cost大于等于10000。

读者可以分别设置条件。当流程变量中的cost变量设置小于1万时,流程表现与排他网关类似;当流程变量中的cost变量设置大于等于1万时,流程表现与并行网关类似。

本文通过数据库跟踪流程,分析了并行网关、排他网关和包含网关的作用与效果。值得注意的是当流程处于并行状态时,执行表act_ru_execution中的IS_SCOPE、IS_CONCURRENT、IS_ACTIVE等都有所不同。以后阅读源码时会发现,这几项都会对活动的行为类有所影响。

activiti学习(十六)——并行网关、排他网关、包含网关相关推荐

  1. OpenCV与图像处理学习十六——模板匹配

    OpenCV与图像处理学习十六--模板匹配 一.模板匹配介绍 二.代码应用 一.模板匹配介绍 模板匹配是一种最原始.最基本的模式识别方法,研究某一特定目标的图像位于图像的什么地方,进而对图像进行定位. ...

  2. PyTorch框架学习十六——正则化与Dropout

    PyTorch框架学习十六--正则化与Dropout 一.泛化误差 二.L2正则化与权值衰减 三.正则化之Dropout 补充: 这次笔记主要关注防止模型过拟合的两种方法:正则化与Dropout. 一 ...

  3. Slicer学习笔记(五十六)slicer分割transformNode包含的信息与使用

    Slicer学习笔记(五十六)slicer分割transformNode包含的信息与使用 1.打印transformNode信息 2.测试 2.1.变换前 2.2.变换后 3.使用坐标变换 1.打印t ...

  4. Python的学习(十六):对文件的操作

    Python的学习(十六):对文件的操作 编码格式的介绍 Python中的解释器使用的是Unicode(内存) .py文件在磁盘上使用UTF-8存储(外存) 如何修改文件格式?不写的话默认为UTF-8 ...

  5. 强化学习(十六) 深度确定性策略梯度(DDPG)

    在强化学习(十五) A3C中,我们讨论了使用多线程的方法来解决Actor-Critic难收敛的问题,今天我们不使用多线程,而是使用和DDQN类似的方法:即经验回放和双网络的方法来改进Actor-Cri ...

  6. java 集合读写同步_JAVA多线程学习十六 - 同步集合类的应用

    1.引言 在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的.在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操 ...

  7. Java多线程学习十六:读写锁 ReadWriteLock 获取锁有哪些规则

    读写锁 ReadWriteLock 获取锁有哪些规则呢? 在没有读写锁之前,我们假设使用普通的 ReentrantLock,那么虽然我们保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进 ...

  8. JVM深入学习(十六)-垃圾回收器的分类和性能指标

    1. 垃圾回收器的分类 1.1 按垃圾回收线程分 按垃圾回收的线程分,分为串行垃圾回收器(Serial)和并行垃圾回收器(Parallel) 1.1.1 串行垃圾回收器(Serial Collecto ...

  9. opencv学习十六:圆检测

    圆检测 原理 圆周上任意三点所确定的圆,经Hough变换后在三维参数空间应对应一点.遍历圆周上所有点,任意三个点所确定的候选圆进行投票.遍历结束后,得票数最高点(理论上圆周上任意三点确定的圆在Houg ...

  10. map赋值给另一个map_Java学习(十六): Lambda操作Map

    1. Java8新加入的lambda方法 由于继承关系,他们相应的子类也都会继承这些新方法. 2. forEach() 该方法签名为void forEach(BiConsumer super K,? ...

最新文章

  1. Java多线程引发的性能问题,怎么解决?
  2. matlab2018a安装后帮助文档打不开解决方法
  3. python四十二:类和对象
  4. 《程序员面试金典》输出单层节点
  5. jenkins 使用xctool 爆出: line 6: xctool: command not found
  6. UVA 11584—— Partitioning by Palindromes
  7. 软件设计的火花——Brooks新作及《人月神话》三十五周年讨论会纪要
  8. 从零开始学PowerShell(2)管道的作用
  9. 微擎乐慧云智慧农场源码V1.0.1
  10. 虚拟机网络无法连接问题解决(超简单)
  11. 1月全球Web服务器市场:Apache份额回升至41.64%
  12. 大佬怼国产特斯拉:将必遭这款车型碾压
  13. 基于javaweb+jsp+mysql的高校家教管理系统
  14. PostgreSQL 最佳实践 - 在线增量备份与任意时间点恢复
  15. Thread.SetData与ThreadStatic
  16. 一次性搞清楚线上CPU100%,频繁FullGC排查套路
  17. 【DVRP】基于matlab遗传和粒子群算法求解带距离的车辆路径规划问题【含Matlab源码 1036期】
  18. oracle jde开发,第一个JDE报表开发
  19. 阿里云公司简介介绍资料
  20. LCS (动态规划)

热门文章

  1. python中生日悖论分析_python实现生日悖论分析
  2. 使用jquery实现的循环连续可停顿滚动
  3. 微软爱开发者 | 十月,“拾月”, Teams + PowerPlatform 中文社区召唤您
  4. 手机版c语言编译器能画图,大佬们,小菜鸟想问一问用vc编译器做简易画图软件...
  5. 位、比特(bit)、字节(byte)、字(个人理解为汉字)
  6. NP难问题以及近似算法(基于次模)
  7. scrapy学习笔记
  8. Ubuntu中vi的使用详解
  9. 如何看待 DeepMind 论文宣称构建通用人工智能的所有技术已经具备?
  10. onBlur事件与onfocus事件(jquery)