參考文章:http://huan1993.iteye.com/blog/2249764 第一部分是部署檔案的大緻說明,其他文章也有介紹,熟悉的可以跳過
首先部署檔案中:
<userTask id="_7" name="評估" flowable:assignee="${per}">
<extensionElements>
<flowable:taskListener event="complete" class="com.taikang.sorceress.modules.workflow.listener.IdeaTaskListener"></flowable:taskListener>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
<multiInstanceLoopCharacteristics isSequential="false" flowable:collection="pers" flowable:elementVariable="per">
<completionCondition>${multiInstance.accessCondition(execution)}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
userTask标簽中 ,flowable:assignee 表示取得multiInstanceLoopCharacteristics标簽中flowable:elementVariable的值,而flowable:elementVariable的值表示flowable:collection這個審批人集合變量的每一個審批人變量;
extensionElements标簽中,設定的是綁定的TaskListener;
multiInstanceLoopCharacteristics 标簽中,設定的是多執行個體特點,其中:
isSequential屬性表示是否串行,串行也就是說是否按順序挨個兒執行。
flowable:collection是在上一個任務節點中放在map裡的key值。
ExecutionListener和TaskListener以及多執行個體任務結束條件類
下面說一下多執行個體任務的配置設定人環節以及結束條件部分。
配置設定人可以像其他文章一樣使用ServiceTask讀取上個節點存儲的審批人。我是覺得必要性不大,直接在上個任務節點把審批人的集合存到map裡完成任務即可。
map.put(“pers”, Arrays.asList(pers_arr));
taskService.complete(taskId, map);
類似于這樣。注意map的key和部署檔案中flowable:collection的值相同即可。
然後說一下多執行個體任務結束條件判定部分的坑。我當時看其他文章一直不明白為什麼有了結束條件類還要綁TaskListener類,同樣都可以用作監聽完成任務之後的回調。
關鍵就在于ExecutionListener與TaskListener的可複寫方法notify。這個方法的參數是DelegateExecution與DelegateTask。這兩個類官方API的解釋是 used in JavaDelegates and ExecutionListeners以及used in JavaDelegates and DelegateListeners。而JavaDelegates是用ServiceTask配置設定審批人的方式,是直接在DelegateExecution的變量調用setVariable方法設定審批人的。
這兩種設定審批人的方法其實都是設定在了多執行個體任務所處的execution裡的,是以均可。
差別在于多執行個體任務每次每個審批人comlete了之後。
首先說一下調用順序,當taskService.complete(taskId, map)調用完之後,如果TaskListener的監聽事件設定為comlete,那麼這裡會先觸發TaskListener中的notify方法,之後再觸發結束條件類的自定義結束函數。并且多執行個體任務中每次complete了之後都會順序觸發這兩個類中的回調函數。
這是我的結束條件判斷類:
public class MultiInstanceCompleteTask implements Serializable {
/**
* 評估結果判定條件
* @param execution 配置設定執行執行個體
*/
public boolean accessCondition(DelegateExecution execution){
//已完成的執行個體數
int completedInstance = (int)execution.getVariable("nrOfCompletedInstances");
//否決判斷,一票否決
if (execution.getVariable(“reject”) != null){
int rejectCount = (int)execution.getVariable(“reject”);
if(rejectCount > 0 ){
//輸出方向為拒絕
execution.setVariable("outcome", “reject”);
//一票否決其他執行個體沒必要做,結束
return true;
}
}
//所有執行個體任務未全部做完則繼續其他執行個體任務
if(completedInstance != sum){
return false;
}else{
//輸出方向為贊同
execution.setVariable("outcome",“approved”);
//所有都做完了沒被否決,結束
return true;
}
}
我部署檔案代碼中multiInstance.accessCondition(execution)對應的便是此處。其中的mulitiInstance如果是和spring整合了,就是spring管理的bean的id,否則就是流程變量的key。
我遇到的坑在于無論你在多執行個體任務調用taskService.complete(taskId, map)之前往map裡存了什麼,在這個結束條件類裡都是取不到的。
原因在于這裡的回調參數是DelegateExecution類,是整體多執行個體任務的環境,在執行其中一個任務時是取不到的。
可以取到的類是DelegateTask類,是以我們每個執行個體的執行結果處理,應寫在TaskListener類中,而結束條件類用作對TaskListener中的處理結果(包括各種結果的計數等)進行判斷,然後在DelegateExecution的變量中設定輸出方向是通過還是駁回等。這裡判斷函數的傳回時是個boolean,它表示整個多執行個體任務節點是否結束,結束的意思是再進行下一個或其他多執行個體任務,還是将其他多執行個體任務短路掉直接結束,根據方法中setVariable中的值決定之後走向。也就是說boolean不代表接受或駁回,而是代表多執行個體任務節點是否提前結束。
另外計數變量的初值應在多執行個體任務節點錢的連線上綁定的ExecutionListener中設定,因為這才能作用于整個多執行個體任務。如果你在執行多執行個體任務中的某一個時是取不到的。代碼如下:
public class IdeaExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) {
delegateExecution.setVariable("unrelated",0);
delegateExecution.setVariable("rejected",0);
}
}
TaskListener示例
public class IdeaTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
//result的值為控制類中taskService.complete(taskId, map)時,map中所設
String result = (String) delegateTask.getVariable("result");
//ExecutionListner類中設定的拒絕計數變量
int rejectedCount = (int)delegateTask.getVariable(“reject”);
if(“reject”.equals(result)){
//拒絕
delegateTask.setVariable("rejected", ++rejectedCount);
}
}
另附判斷結果類中流程引擎自帶可用變量:
1.nrOfInstances 該會簽環節中總共有多少個執行個體