Activiti 使用者任務並行動態多例項(多使用者執行流程)
在很多情況下,我們需要多使用者共同執行餘下流程,比如開會流程:
- 領導發起開會,選擇開會人員(多個)
- 每個開會人員接收到通知後需要簽到(一名使用者簽到不會影響到另一位使用者的簽到)
- 簽到完成後則流程結束
如果只使用代理(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動態多例項完成。