應用場景:
多個部門發起資金計劃,最後統一到財務部審批,每個部門發起資金計劃是一個子流程,財務部審批是多個部門的計劃同時審批,審批完成後,再提交上級領導審批。
流程如下:
要解決以上問題,需要實現多個子流程並行處理的功能。在Activiti5有一個比較強的節點屬性就是多實例,它可以支持多實例的子流程,多實例任務,多實體腳本等。目前支持多實例的節點類型有:
多實例還有並行、串行區分。以下解釋一下什麼是並行與串行
並行代表同時進行,如把任務分給5個人來處理,這5個人同時會收到任務,並且可以同時處理,不受各自的影響。
串行代表工作或任務由一個人完成後,再由另一個人去處理,直至全部完成,每個任務依賴於前一個任務完成。
會籤任務即可以由activiti多實例任務節點來實現,(上一博客有介紹如何開發設計會籤任務)
在Activiti的定義中,生成多實例的定義很簡單,只需要如下類似去生成以下標籤,則可以完成多實例的聲明,如下所示,我們要支持並行節點的多實例的定義
多實例人工任務
<userTask activiti:assignee="${assignee}" id="SignTask2" name="財務主管會籤">
<extensionElements>
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskSignCreateListener"
event="create" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskAssignListener"
event="assignment" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"
event="complete" />
</extensionElements>
<multiInstanceLoopCharacteristics
activiti:elementVariable="assignee" isSequential="false"
activiti:collection="${taskUserAssignService.getSignUser(execution)}">
<completionCondition>${signComplete.isComplete(execution) }
</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
多實例子流程
<subProcess activiti:assignee="${assignee}" id="SubProcess1"
name="部門資金計劃流程">
<startEvent activiti:initiator="startUser" id="startEvent2"
name="開始" />
<endEvent id="endEvent1" name="結束1" />
<userTask id="task3" name="助理填寫">
<documentation />
<extensionElements>
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskCreateListener"
event="create" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskAssignListener"
event="assignment" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"
event="complete" />
</extensionElements>
</userTask>
<userTask id="task4" name="部門領導審查">
<documentation />
<extensionElements>
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskCreateListener"
event="create" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskAssignListener"
event="assignment" />
<activiti:taskListener
class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"
event="complete" />
</extensionElements>
</userTask>
<sequenceFlow sourceRef="startEvent2" targetRef="task3"
id="sequenceFlow1" name="" />
<sequenceFlow sourceRef="task3" targetRef="task4" id="sequenceFlow2"
name="" />
<sequenceFlow sourceRef="task4" targetRef="endEvent1" id="sequenceFlow3"
name="" />
<extensionElements>
<activiti:executionListener event="start"
class="com.hotent.platform.service.bpm.listener.StartEventListener" />
<activiti:executionListener event="end"
class="com.hotent.platform.service.bpm.listener.EndEventListener" />
</extensionElements>
<multiInstanceLoopCharacteristics
activiti:elementVariable="assignee" isSequential="false"
activiti:collection="${taskUserAssignService.getMultipleUser(execution)}" />
</subProcess>
所以關鍵的配置屬性:
<multiInstanceLoopCharacteristics
activiti:elementVariable="assignee" isSequential="false"
activiti:collection="${taskUserAssignService.getSignUser(execution)}">
<completionCondition>${signComplete.isComplete(execution) }
</completionCondition>
</multiInstanceLoopCharacteristics>
我們在控制多實例的個數或人數時,是通過taskUserAssignService的getSignUser獲取或getMultipleUser(execution)其集合的個數,從而決定產生多少個實體任務或子流程。
如實現子流程多實例的獲取人數,則來自:
/**
* 獲取多實體子流程的執行用戶集合
* @param execution
* @return
* @throws Execption
*/
public List<String> getMultipleUser(ActivityExecution execution) throws Exception{
String nodeId=execution.getActivity().getId();
ExecutionEntity executionEnt=(ExecutionEntity) execution;
List<String> userIds=(List<String>)execution.getVariable(BpmConst.SUBPRO_MULTI_USERIDS);
if(userIds!=null) return userIds;
Map<String,FlowNode> nodeMap= NodeCache.getByActDefId(executionEnt.getProcessDefinitionId());
FlowNode subProcessNode=nodeMap.get(nodeId);
FlowNode firstNode=subProcessNode.getSubFirstNode();
FlowNode secodeNode=firstNode.getNextFlowNodes().get(0);
List<String> userList=nodeUserMapLocal.get().get(secodeNode.getNodeId());
logger.debug("userList size:" + userList.size());
execution.setVariable(BpmConst.SUBPRO_MULTI_USERIDS, userList);
return userList;
}
因爲該方法會被調用多次,所以其實現的思路是第一次其集合是來自用戶的界面選擇的人員列表,第一次之後,放到流程變量中去,在後續的獲取中,直接從流程變量中獲取。
然後在任務的創建的監聽器中,從流程變量assignee中獲取當前任務的執行人。以上的實現還有一細節就是要解決如何查找到子流程中的第一個任務節點,並且把對應的任務人員授給這任務節點。
更多資訊請加QQ瞭解1361783075