Activiti 開發案例之多實例並行子流程
- 2019 年 12 月 5 日
- 筆記
概念
Activiti 提供了兩種基於子流程的實現:
- 一種是內嵌子流程:子流程元素
<subProcess>
內嵌在主流程元素<process>
之內,只能在該流程中使用該子流程,外部是無法訪問到的。這種子流程一般作為局部通用邏輯處理,或者因為特定業務需要,使得比較複雜的單個主流程設計清晰直觀。 - 另一種是調用子流程:首先實現一個流程,在另一個流程中可以調用該流程,通常可以定義一些通用的流程作為這種調用子流程,供其他多個流程定義復用。這種子流程使用
<callActivity>
元素來進行調用,間接地嵌入到主流程中,用起來比較方便。
流程圖
以上是一個公司內部合同評審的內嵌子流程流程圖,一個合同的通過是需要經過多個部門的層層審核,最終才得以通過。
- 銷售發起合同評審流程
- 進入子流程,各個部門根據實際情況進行多級審批
- 各個部門審批通過,流程結束
生成子流程
XML部分代碼
/** * 博客 https://blog.52itstyle.vip */ <subProcess id="subprocess" name="合同評審"> <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee"> <completionCondition>${nrOfCompletedInstances/nrOfInstances==1}</completionCondition> </multiInstanceLoopCharacteristics> <!--省略相關任務節點代碼--> </subProcess>
- collection:存放集合,集合中可以存任意值,工作流會根據你集合里的值個數,去生成對應的子流程,這裡我們存放一級審批的用戶ID。
- elementVariable:節點流程變量,用於在流程圖中代替集合中表示當前子流程的變量,對應子流程中第一個任務節點的變量名。
- completionCondition:完成條件,這裡寫的表達式如果滿足即可流轉到下一步。
發起
成功發起之後,系統會自動生成集合數量的任務(子流程),然後在每個子流程中設置與業務流程相關的局部變量。
/** * 博客 https://blog.52itstyle.vip */ Map<String, Object> variables = new HashMap<>(); //4個部門審核,生成4個流程,集合中獲取並存放的是一級評審人 List<String> assigneeList= Arrays.asList(new String[] {"1","2","3","4"}); variables.put("assigneeList", assigneeList); ProcessInstance in = runtimeService.startProcessInstanceByKey("contract_review", variables); List<Task> list = taskService.createTaskQuery().processInstanceId(in.getId()).list(); System.out.println("任務數量:"+list.size()); list.forEach(task -> { /** * 模擬幾級審批(正式環境要從配置或者數據庫讀取),因為這裡要清楚每個部門走幾級審批邏輯 * 變量存放到每個任務節點的全局任務變量中 */ Random r = new Random();//創建隨機種子,Random對象 int rank = r.nextInt(3)+1; System.out.println("任務ID:"+task.getId()); System.out.println("指派人ID:"+task.getAssignee()); //保存在整個子流程中 runtimeService.setVariableLocal(task.getExecutionId(),"rank",rank); });
審核
這裡只說幾個比較重要的點,大家可以根據自身業務場景處理。
/** * 博客 https://blog.52itstyle.vip */ //獲取當前任務 Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); //獲取當前任務Code String taskCode = task.getTaskDefinitionKey(); //獲取當前任務流轉唯一ID String executionId = task.getExecutionId(); //獲取當前子流程任務變量 Object rank = runtimeService.getVariableLocal(task.getExecutionId(),"rank"); //認領任務 variables.put("approve",rank); taskService.claim(taskId, userId); taskService.complete(taskId, variables); //這裡要判斷當前子流程是一級審批、如果是二級審批或者三級審批還需要獲取下級任務節點 task = taskService.createTaskQuery().executionId(executionId).active().singleResult(); //指派任務 taskService.addCandidateUser(task.getId(),reviewUserId);
小結
子流程的概念用途還是比較廣泛的,基本上企業內部涉及到多部門合作的流程都有可能用到,這裡需要注意的是,由於業務類型不同,每個子流程的相關邏輯判斷也可能不同,這就需要在每個子流程中存儲流程變量,用於各級流程邏輯判斷。