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

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

并行网关

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

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

这里用菱形里面一个“+”的图案表示并行网关,左边的表示分支,右边的表示聚合。我们启动流程之后看看数据库情况。并行网关的“出线”属于无条件走出,即使在“出线”上设置了条件,也不会影响其效果。具体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等都有所不同。以后阅读源码时会发现,这几项都会对活动的行为类有所影响。

相关推荐
<p> <b><span style="font-size:14px;"></span><span style="font-size:14px;background-color:#FFE500;">【Java面试宝典】</span></b><br /> <span style="font-size:14px;">1、68讲视频课,500道大厂Java常见面试题+100个Java面试技巧与答题公式+10万字核心知识解析+授课老师1对1面试指导+无限次回放</span><br /> <span style="font-size:14px;">2、这门课程基于胡书敏老师8年Java面试经验,调研近百家互联网公司及面试官的问题打造而成,从筛选简历和面试官角度,给出能帮助候选人能面试成功的面试技巧。</span><br /> <span style="font-size:14px;">3、通过学习这门课程,你能系统掌握Java核心、数据库、Java框架、分布式组件、Java简历准备、面试实战技巧等面试必考知识点。</span><br /> <span style="font-size:14px;">4、知识点+项目经验案例,每一个都能做为面试的作品展现。</span><br /> <span style="font-size:14px;">5、本课程已经在线下的培训课程中经过实际检验,老师每次培训结束后,都能帮助同学们运用面试技巧,成功找到更好的工作。</span><br /> <br /> <span style="font-size:14px;background-color:#FFE500;"><b>【超人气讲师】</b></span><br /> <span style="font-size:14px;">胡书敏 | 10年大厂工作经验,8年Java面试官经验,5年线下Java职业培训经验,5年架构师经验</span><br /> <br /> <span style="font-size:14px;background-color:#FFE500;"><b>【报名须知】</b></span><br /> <span style="font-size:14px;">上课模式是什么?</span><br /> <span style="font-size:14px;">课程采取录播模式,课程永久有效,可无限次观看</span><br /> <span style="font-size:14px;">课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化</span><br /> <br /> <br /> <span style="font-size:14px;background-color:#FFE500;"><strong>如何开始学习?</strong></span><br /> <span style="font-size:14px;">PC端:报名成功后可以直接进入课程学习</span><br /> <span style="font-size:14px;">移动端:<span style="font-family:Helvetica;font-size:14px;background-color:#FFFFFF;">CSDN 学院APP(注意不是CSDN APP哦)</span></span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页