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);

小結

子流程的概念用途還是比較廣泛的,基本上企業內部涉及到多部門合作的流程都有可能用到,這裡需要注意的是,由於業務類型不同,每個子流程的相關邏輯判斷也可能不同,這就需要在每個子流程中存儲流程變量,用於各級流程邏輯判斷。