如何控制工作流中的流程流轉?工作流流程元素之順序流和網關的詳細解析


順序流

描述
  • 順序流是連接兩個流程節點的連線
  • 流程執行完一個節點后,會沿着節點的所有外出順序流繼續執行
  • 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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM