1簡介
做工作流,基本會遇到會簽、或簽的需求。而flowable是通過多任務方式來實現(xiàn)的
2主要實現(xiàn)方式
在流程運行到任務節(jié)點時不是按照默認規(guī)則只生成一條任務記錄,而是根據(jù)需要同時生成多條任務記錄,甚至生成的多條任務都能分別對應到指定的各個審批人。而不再需要領取。這種就叫多任務
要實現(xiàn)多任務,則需要對 需要的任務節(jié)點需要做相關處理
下面介紹了解到兩種方式處理
2.1 xml方式
此種方式是直接通過在xml的相應節(jié)點來定義多任務,這種官方有大量的xml 例子
使用flowable 官方的套件來配置多任務的交互見面大概如下(圖片來源于網(wǎng)上):
[圖片上傳失敗...(image-211f1c-1666348348264)]
最終對應到實際的核心xml詳細如下 (下面xml不嚴格對應上圖)
<bpmn2:userTask id="Activity_1g65lke" name="審批啊14" flowable:assignee="${assignee}" flowable:candidateGroups="2317,2347" flowable:category="CHECK">
<bpmn2:extensionElements>
<flowable:executionListener class="***.listens.MultiInstanceListen" event="start" />
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_1666168081285</bpmn2:incoming>
<bpmn2:outgoing>Flow_03sldqb</bpmn2:outgoing>
<bpmn2:multiInstanceLoopCharacteristics isSequential="false" flowable:collection="assigneeList" flowable:elementVariable="assignee">
<bpmn2:extensionElements>
</bpmn2:extensionElements>
<bpmn2:completionCondition>${nrOfCompletedInstances>=1}</bpmn2:completionCondition>
</bpmn2:multiInstanceLoopCharacteristics>
</bpmn2:userTask>
如果你不是用的官方的UI來生成的xml, 那么你的自己想辦法也需要構造出上面的xml
2.2 java類后端處理
此種方式是我在調研時看到的,我并未嘗試過,不太切合我們的需求,但是也是一種方式
此種方式就是運行到相應節(jié)點,后端通過調用api來生成多任務所需要的一切
這邊就不放核心代碼了,直接可以點擊網(wǎng)友已經(jīng)做好的整理
3 核心參數(shù)解釋
上面應該能看到我們需要配置一些東西才能支持多任務。這里詳細說下相關參數(shù)及重要點
3.1 相關參數(shù)
isSequential: 表示并行,還是順序。(xml跟配圖可能有出入)
-
loop cardinality:循環(huán)基數(shù)??蛇x項??梢灾苯犹钫麛?shù),表示會簽、或簽的人數(shù) - (會創(chuàng)建基數(shù)個任務實例)
使用該參數(shù)只能保證生成相應的任務,但是生成的任務沒有assign
該參數(shù)跟下面 collection 二選一就行
flowable:collection: 此種方式是表示的會簽、或簽的具體人。這里xml只需要約定好固定的格式 即可。比如 flowable:collection="assigneeList"
flowable:elementVariable: 元素變量, 這里xml只需要約定好固定的格式 即可 flowable:elementVariable="assignee"
-
completionCondition:完成條件。這個條件控制著這里是會簽、或簽如何才能算完成。
- nrOfCompletedInstances: 完成的任務實例數(shù)
- nrOfInstances: 總共生成的任務實例數(shù)(根據(jù)會簽、或簽指定的人數(shù)生成相應的任務數(shù))
參考配置
當是或簽時,直接固定配置: ${nrOfCompletedInstances>=1} 即可
當是會簽時,固定配置: ${nrOfCompletedInstances==nrOfInstances} 即可
3.2 重要點
在會簽、或簽節(jié)點增加 multiInstanceLoopCharacteristics 相應的標簽
指定生成的任務數(shù)。這里更建議使用 collection。 因為它可以相關配置做到 給生成的任務實例時就有assign
-
任務標簽上屬性 flowable:assignee="${assignee}" 必須固定這么指定,否則創(chuàng)建的多任務記錄里面 assign還是沒值
屬性assignee 取 Element varible的值,比如Element varible設置為assignee,Assignents就設置為${assignee}
如果節(jié)點是審批節(jié)點,那么一定需要在用戶任務節(jié)點 的
extensionElements下添加 監(jiān)聽器
4 collection 賦值
4.1 使用原因
首先我們?yōu)槭裁匆褂?collection 再次簡單說下,通過上面的配置,當指定了 collection 的流程變量后,在引擎自動生成多任務時每個任務的assign都有值了。就不再需要增加業(yè)務邏輯處理(遍歷多任務后然后拿到審批人,依次給每個任務塞 處理人)
4.2 如何賦值
做下來覺得最難的地方就是 collection 賦值的問題。思路線索很多,但是都存在問題
4.2.1 官方
首先說還是說官方的例子 點擊查看MultiInstanceTest
里面竟然是通過在發(fā)起流程就指定了審批人。這種也太DEMO了點。審批人即使是配置時固定的人,在開始發(fā)起流程就有知道審批人,那么就需要去解析xml, 找到相應節(jié)點的審批人。這種一開始只被我用來做最后的打算
官方還給出另一種表達式方案 點擊查看multiinstancemodel.bpmn
<endEvent id="sid-194696BA-1A7D-47D7-95A9-A77390D25048"></endEvent>
<userTask id="userTask1" name="User task 1" flowable:async="true" flowable:exclusive="false">
<multiInstanceLoopCharacteristics isSequential="false" flowable:elementVariable="participant">
<extensionElements>
<flowable:collection flowable:class="org.flowable.engine.test.bpmn.multiinstance.JSONCollectionHandler">
<flowable:string>
<![CDATA[[
{
"principalType" : "User",
"role" : "PotentialOwner",
"principal" : "wfuser1",
"version" : 1
},
{
"principalType" : "User",
"role" : "PotentialOwner",
"principal" : "wfuser2",
"version" : 1
}
]]]>
</flowable:string>
</flowable:collection>
</extensionElements>
</multiInstanceLoopCharacteristics>
</userTask>
然后這種方式我是各種嘗試,但是在流程走到該節(jié)點就出現(xiàn)解析不成功問題
最后我也查到了這種方式的來源是這篇帖子 Multi-instance collection syntax proposal 有更感興趣的可以去看看
4.2.2 事件
在嘗試使用上面方式失敗后,我開始嘗試用監(jiān)聽事件的方式來賦值collection 。
我嘗試過 FlowableEngineEventType.ACTIVITY_STARTED 事件 , FlowableEngineEventType.TASK_CREATED 事件
但是發(fā)現(xiàn)都不行,他們都是在多任務已經(jīng)創(chuàng)建完后才會執(zhí)行相關的事件方法。這個時候已經(jīng)生成的多個任務,但是它們的assign都是空的
4.2.3 執(zhí)行監(jiān)聽器
我在網(wǎng)上查詢方案,終于在一篇文中 activiti多實例設置(會簽/或簽) 看到能在任務創(chuàng)建前賦值collection 的可能。
然后我根據(jù)這個信息查到配置執(zhí)行監(jiān)聽器最終做到在正確時機給 collection 賦值
首先,需要在xml需要添加監(jiān)聽器 (完整可以看看上面的xml)
<flowable:executionListener class="***.listens.MultiInstanceListen" event="start" />
然后看看實現(xiàn)
/**
* 多任務監(jiān)聽,主要是把 多人任務xml設置的集合給填充掉
*/
@Component
@Slf4j
public class MultiInstanceListen implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
FlowElement element = execution.getCurrentFlowElement();
if (element instanceof UserTask) {
UserTask userTask = (UserTask) element;
List<String> candidateGroups = userTask.getCandidateGroups();
// 設置 setVariableLocal 會導致找不到 assigneeList 變量
execution.setVariable("assigneeList", candidateGroups);
}
}
}
通過此方式,就會在創(chuàng)建多任務之前執(zhí)行該監(jiān)聽器,從而讓 assigneeList 集合存放在流程變量中