背景
因業務需求需要實現指定多人來進行一個task,傳統做法是使用網關來達到目的,但是顯示情況是會審的人員是可變且易變的,比如我指定安全組來做一個檢驗任務,安全組今天可能是5個人,明天又有人離職變成了3個人,因此網關不大適合該場景,這裏就需要用到activiti提供的parallel。
環境
activiti 5.19.0~5.22.0皆可
概念
Activiti User Guide 8.5.14. Multi-instance (for each)中有介紹,即設定一個task爲sequentially(順序執行)或parallel(並行執行)。前者在數據庫中一次只產生一個task記錄,順序執行;後者產生多個記錄,並行執行。
實現
本文流程要實現以下功能
提交一個測試申請,流轉到並行任務,並行任務中各個執行人通過條件選擇是否通過(網上流傳的${nrOfCompletedInstances/nrOfInstances >= x }並沒有提供條件選擇的情況,且nrOfCompletedInstances與form表單條件無關)。
總體流程圖如下
幾個需要編輯的地方
1、第一個任務(t1)
需要添加一個自定義的task listener用來處理變量以及設置t2中會審的人員,比如在這個監聽器中就可以通過groupID之類的參數去獲取成員列表。
這裏提供類代碼,以作參考
public class MutiGroupsListener implements TaskListener {
public static final Logger LOGGER = LoggerFactory
.getLogger(MutiGroupsListener.class);
@Override
public void notify(DelegateTask arg0) {
//清0操作,如果t2會審步驟被駁回,回到t1,需要將通過數,總數重新清空
if(arg0.getVariable("passCount")!=null){
arg0.setVariable("passCount", 0);
}
if(arg0.getVariable("totalCount")!=null){
arg0.setVariable("totalCount", 0);
}
//添加會籤的人員,這裏可以根據自己的業務邏輯去動態獲取列表
List<String> assigneeList = new ArrayList<String>();
assigneeList.add("kermit");
assigneeList.add("gonzo");
arg0.setVariable("partyList",assigneeList);
}
}
2、第二個任務(t2)
在這裏我們需要將task設置爲parallel,XML採用如下設置:
<multiInstanceLoopCharacteristics isSequential="false">
...
</multiInstanceLoopCharacteristics>
設計器如圖:
其後,設置會籤人員集合名稱以及集合項名稱,任務的辦理人使用項名稱獲取。
表單選擇項:
t2完成任務需要調用的方法
public void completeTask(String taskId,String instanceId,String passflag){
ProcessEngine processEngine =ProcessEngines.getDefaultProcessEngine();
List<Task> tasks = processEngine.getTaskService().createTaskQuery().taskName("t2").processInstanceId("instanceId").list();
int count = 0;
int totalCount = 0;
for(Task tmp:tasks){
String tmpCount = processEngine.getTaskService().getVariable(tmp.getId(), "passCount")+"";//獲取通過記錄數,這裏不能使用nrOfCompletedInstances,因爲與我們業務無關
String tmpTotal = processEngine.getTaskService().getVariable(tmp.getId(), "totalCount")+"";//獲取記錄總數
if(!tmpCount.equals("null") && !tmpCount.trim().equals("")){
count = Integer.parseInt(tmpCount);
}
if(!tmpTotal.equals("null") && !tmpTotal.trim().equals("")){
totalCount = Integer.parseInt(tmpTotal);
}
System.out.println(tmp.getId()+"var = "+passflag);
if(passflag.equals("yes")){//選擇通過則+1
count++;
}
totalCount++;
}
Map<String, Object> vars = new HashMap<String,Object>();
//變量回寫記錄
vars.put("passCount", count);
vars.put("totalCount", totalCount);
processEngine.getTaskService().complete(taskId,vars);
}
表單條件查詢,可以返回給頁面,根據內容初始化頁面組件
public void queryFormMsg(String taskId) {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskFormData td = processEngine.getFormService().getTaskFormData(taskId);
List<FormProperty> pros = td.getFormProperties();
for(FormProperty tmp:pros){
System.out.println("pid:"+tmp.getId());
System.out.println("pname:"+tmp.getName());
System.out.println("pvalue:"+tmp.getValue());
System.out.println("ptype:"+tmp.getType().getName());
System.out.println("=========");
}
}
3、條件判斷
這裏設置如果全票通過則結束流程,否則返回t1,重新上傳文件或是設置信息,這裏根據業務而定。
測試,第一次循環一人選擇”no”一人選擇”yes”,然後第二次全部選擇“yes”,通過歸檔。(這裏流程啓動、執行全部使用了自己寫的方法,流程設計、記錄查詢借用了activiti explorer)