Flowable中的各種網關,你知道幾個?
網關
網關用來控制流程的流向。
1.排他網關
排他網關(exclusive gateway)(也叫異或網關 XOR gateway,或者更專業的,基于數據的排他網關 exclusive data-based gateway),用于對流程中的決策建模。當執行到達這個網關時,會按照所有出口順序流定義的順序對它們進行計算。選擇第一個條件計算為true的順序流(當沒有設置條件時,認為順序流為true)繼續流程。
請注意這里出口順序流的含義與BPMN 2.0中的一般情況不一樣。一般情況下,會選擇所有條件計算為true的順序流,并行執行。而使用排他網關時,只會選擇一條順序流。當多條順序流的條件都計算為true時,會且僅會選擇在XML中最先定義的順序流繼續流程。如果沒有可選的順序流,會拋出異常。
排他網關用內部帶有’X’圖標的標準網關(菱形)表示,'X’圖標代表異或的含義。請注意內部沒有圖標的網關默認為排他網關。BPMN 2.0規范不允許在同一個流程中混合使用有及沒有X的菱形標志。
案例:
/**
* 部署流程
*/
@Test
public void deploy(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("請假流程-排他網關.bpmn20.xml")
.name("請求流程-排他網關")
.deploy();
System.out.println("deploy.getId() = " + deploy.getId());
System.out.println(deploy.getName());
}
/**
* 啟動流程實例
*/
@Test
public void runProcess(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 給流程定義中的UEL表達式賦值
Map<String,Object> variables = new HashMap<>();
// variables.put("g1","group1");
variables.put("num",3); // 給流程定義中的UEL表達式賦值
runtimeService.startProcessInstanceById("holiday-exclusive:1:4",variables);
}
/**
* 啟動流程實例
*/
@Test
public void setVariables(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 給流程定義中的UEL表達式賦值
Map<String,Object> variables = new HashMap<>();
// variables.put("g1","group1");
variables.put("num",4); // 給流程定義中的UEL表達式賦值
runtimeService.setVariables("12503",variables);
}
/**
* 完成任務
*/
@Test
public void completeTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
//.processInstanceId("2501")
.processDefinitionId("holiday-exclusive:1:4")
.taskAssignee("zhangsan")
.singleResult();
if(task != null){
// 完成任務
taskService.complete(task.getId());
System.out.println("完成Task");
}
}
如果從網關出去的線所有條件都不滿足的情況下會拋出系統異常。
但是要注意任務沒有介紹,還是原來的任務,我們可以重置流程變量。
@Test
public void setVariables(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 給流程定義中的UEL表達式賦值
Map<String,Object> variables = new HashMap<>();
// variables.put("g1","group1");
variables.put("num",4); // 給流程定義中的UEL表達式賦值
runtimeService.setVariables("12503",variables);
}
前面我們可以直接在連接線上定義條件,那為什么還要有排他網關呢?直接在線上的情況,如果條件都不滿足,流程就結束了,是異常結束!
2.并行網關
并行網關允許將流程分成多條分支,也可以把多條分支匯聚到一起,并行網關的功能是基于進入和外出順序流的:
- fork分支:并行后的所有外出順序流,為每個順序流都創建一個并發分支。
- join匯聚: 所有到達并行網關,在此等待的進入分支, 直到所有進入順序流的分支都到達以后, 流程就會通過匯聚網關。
注意,如果同一個并行網關有多個進入和多個外出順序流, 它就同時具有分支和匯聚功能。 這時,網關會先匯聚所有進入的順序流,然后再切分成多個并行分支。
與其他網關的主要區別是,并行網關不會解析條件。 即使順序流中定義了條件,也會被忽略。
案例:
當我們執行了創建請假單后,到并行網關的位置的時候,在ACT_RU_TASK表中就有兩條記錄。
然后同時在ACT_RU_EXECUTION中有三條記錄,一個任務對應的有兩個執行實例。
3.包含網關
包含網關可以看做是排他網關和并行網關的結合體。 和排他網關一樣,你可以在外出順序流上定義條件,包含網關會解析它們。 但是主要的區別是包含網關可以選擇多于一條順序流,這和并行網關一樣。
包含網關的功能是基于進入和外出順序流的:
- 分支: 所有外出順序流的條件都會被解析,結果為true的順序流會以并行方式繼續執行, 會為每個順序流創建一個分支。
- 匯聚:所有并行分支到達包含網關,會進入等待狀態, 直到每個包含流程token的進入順序流的分支都到達。 這是與并行網關的最大不同。換句話說,包含網關只會等待被選中執行了的進入順序流。 在匯聚之后,流程會穿過包含網關繼續執行。
4.事件網關
事件網關允許根據事件判斷流向。網關的每個外出順序流都要連接到一個中間捕獲事件。 當流程到達一個基于事件網關,網關會進入等待狀態:會暫停執行。與此同時,會為每個外出順序流創建相對的事件訂閱。
事件網關的外出順序流和普通順序流不同,這些順序流不會真的"執行", 相反它們讓流程引擎去決定執行到事件網關的流程需要訂閱哪些事件。 要考慮以下條件:
事件網關必須有兩條或以上外出順序流;
事件網關后,只能使用intermediateCatchEvent類型(activiti不支持基于事件網關后連接ReceiveTask);
連接到事件網關的中間捕獲事件必須只有一個入口順序流。