1. 程式人生 > >Activiti 使用者任務並行動態多例項(多使用者執行流程)

Activiti 使用者任務並行動態多例項(多使用者執行流程)

在很多情況下,我們需要多使用者共同執行餘下流程,比如開會流程

  1. 領導發起開會,選擇開會人員(多個)
  2. 每個開會人員接收到通知後需要簽到(一名使用者簽到不會影響到另一位使用者的簽到)
  3. 簽到完成後則流程結束

如果只使用代理(Assignee、Candidate users、Candidate groups) 將無法解決上述問題,因為即使使用 Candidate users ,但每個使用者實際上還是在一個任務裡面,其中一個使用者完成任務,另外的使用者任務也隨之完成,此時,就需要用到多例項(多工)。

以上面開會流程為例:

1. 建立模型

2. 模型相關配置

【領導發起開會】由於具體是哪個領導發起開會有不確定性(只要是領導都可以發起),所以需要設定代理人屬性:Assignee: ${leader}
  -- 此處採用變數形式
為了方便後面的【開發人員簽到】流程,我們還需要在【領導發起開會】流程處設定一個流程執行監聽器(此操作不是必須,此處只是為了解釋動態多例項),在Activiti中,配置監聽器需要在模型和JAVA中都進行相應配置:在JAVA中我們想要建立監聽器只需要建立一個類,並實現系統監聽器類 ExecutionListener 即可,程式碼如下:
package com.kenary.activiti.listener;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;

/** * 自定義監聽器 */ public class MyExecutionListener implements ExecutionListener { @Override public void notify(DelegateExecution delegateExecution) throws Exception { } }

可見此時監聽器沒做任何處理,我們稍安勿躁。接下來就是模型中的配置,由於我們想在領導指派了開會人員後進行監聽,所以需要如下設定

其中 Event 代表事件觸發型別,作用如其名Class 代表監聽器全路徑,此處為 com.kenary.activiti.listener.MyExecutionListener,則是之前建立的 MyExecutionListener

監聽器配置完成後領導發起開會流程就配置完成了!

【開會人員簽到】相對於【領導發起開會】流程,【開發人員簽到】流程則需要配置更多東西

其中,集合(Collection) 設定的是儲存開會人員集合的變數名,注意:此處不需要${},並且 變數的值必須是 Collection的子類,即List、Set等

多例項型別 設定的是 並行、序列 等方式

  並行代表同時進行,如把任務分給5個人來處理,這5個人同時會收到任務,並且可以同時處理,不受各自的影響。

  序列代表工作或任務由一個人完成後,再由另一個人去處理,直至全部完成,每個任務依賴於前一個任務完成。

元素變數(Element variable) 設定的是集合(Collection)每遍歷一次設定的變數值的變數名,即迭代集合時儲存集合裡面單個元素的變數名,集合遍歷時會根據內容建立任務

代理 設定的是處理該任務的使用者,由於集合每遍歷一次就建立了一個任務,所以這裡和領導發起開會流程無太大差異,指定代理人即可,不過代理人員需要使用元素變數(Element variable)(Item 迭代的值)

至此,流程配置基本完成

3. 部署流程

import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.Deployment;......
private RepositoryService repositoryService;
......Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();
            modelData.setDeploymentId("99999");
            repositoryService.saveModel(modelData);

其中,99999 為模型id

4. 領導發起開會

import org.activiti.engine.RuntimeService;.......
@Autowiredprivate RuntimeService runtimeService;
......// 開始-》開啟領導發起開會流程(指定領導)
Map<String,Object> p1 = new HashMap<>();
p1.put("leader","jjh");
runtimeService.startProcessInstanceByKey("10001",map);

其中,"jjh" 為設定的變數值,因為我內部通過使用者名稱來區分,所以直接設定 jjh

 runtimeService.startProcessInstanceByKey("10001",map);   為啟動流程,10001 為流程id

當這步執行完成後,我們來查詢 屬於 jjh 的任務

5. 開會人員簽到開會人員簽到需要設定多個使用者

import org.activiti.engine.TaskService;.......
@Autowiredprivate TaskService taskService;.......Map<String,Object> map = new HashMap<>();
map.put("assigneeList","jjh,yxc");
// 完成任務
teskService.complete("75167", map);

可以看見,我們的使用者設定了多個,並且使用逗號隔開,但是剛才也介紹了 集合(Colloection) 必須是 Collection的子類,也就是 List、Set等,而String不是

所以此時可以回到監聽器,並將其改為:

public class MyExecutionListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution delegateExecution) throws Exception {
        String assigneeList = String.valueOf(delegateExecution.getVariable("assigneeList"));
        if(assigneeList != null){
            // 根據逗號分割並以陣列形式重新設定進去
            delegateExecution.setVariable("assigneeList", Arrays.asList(assigneeList.split(",")));
        }
    }
}

作用是將變數中的字串根據逗號分割成了集合,其實此步驟完全多餘,在設定變數時直接設定集合即可,但是為了順帶加上監聽器的作用,所以則以此種方式說明

6. 效果預覽

當任務執行後,我們分別看看 jjh 和 yxc 雙使用者的任務

可以看到,兩個不同的使用者的任務id是不相同的,所以他們不會互不干擾,Activiti動態多例項完成。