應(yīng)用場(chǎng)景:
多個(gè)部門發(fā)起資金計(jì)劃,,最后統(tǒng)一到財(cái)務(wù)部審批,,每個(gè)部門發(fā)起資金計(jì)劃是一個(gè)子流程,財(cái)務(wù)部審批是多個(gè)部門的計(jì)劃同時(shí)審批,審批完成后,再提交上級(jí)領(lǐng)導(dǎo)審批。
流程如下:
要解決以上問題,,需要實(shí)現(xiàn)多個(gè)子流程并行處理的功能。在Activiti5有一個(gè)比較強(qiáng)的節(jié)點(diǎn)屬性就是多實(shí)例,,它可以支持多實(shí)例的子流程,,多實(shí)例任務(wù),多實(shí)體腳本等,。目前支持多實(shí)例的節(jié)點(diǎn)類型有:
多實(shí)例還有并行,、串行區(qū)分。以下解釋一下什么是并行與串行
并行代表同時(shí)進(jìn)行,,如把任務(wù)分給5個(gè)人來(lái)處理,,這5個(gè)人同時(shí)會(huì)收到任務(wù),并且可以同時(shí)處理,,不受各自的影響,。
串行代表工作或任務(wù)由一個(gè)人完成后,再由另一個(gè)人去處理,,直至全部完成,,每個(gè)任務(wù)依賴于前一個(gè)任務(wù)完成。
會(huì)簽任務(wù)即可以由activiti多實(shí)例任務(wù)節(jié)點(diǎn)來(lái)實(shí)現(xiàn),,(上一博客有介紹如何開發(fā)設(shè)計(jì)會(huì)簽任務(wù))
在Activiti的定義中,,生成多實(shí)例的定義很簡(jiǎn)單,只需要如下類似去生成以下標(biāo)簽,,則可以完成多實(shí)例的聲明,,如下所示,我們要支持并行節(jié)點(diǎn)的多實(shí)例的定義
多實(shí)例人工任務(wù)
- <userTask activiti:assignee="${assignee}" id="SignTask2" name="財(cái)務(wù)主管會(huì)簽">
- <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>
多實(shí)例子流程
- <subProcess activiti:assignee="${assignee}" id="SubProcess1"
- name="部門資金計(jì)劃流程">
- <startEvent activiti:initiator="startUser" id="startEvent2"
- name="開始" />
- <endEvent id="endEvent1" name="結(jié)束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="部門領(lǐng)導(dǎo)審查">
- <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>
所以關(guān)鍵的配置屬性:
- <multiInstanceLoopCharacteristics
- activiti:elementVariable="assignee" isSequential="false"
- activiti:collection="${taskUserAssignService.getSignUser(execution)}">
- <completionCondition>${signComplete.isComplete(execution) }
- </completionCondition>
- </multiInstanceLoopCharacteristics>
我們?cè)诳刂贫鄬?shí)例的個(gè)數(shù)或人數(shù)時(shí),,是通過(guò)taskUserAssignService的getSignUser獲取或getMultipleUser(execution)其集合的個(gè)數(shù),,從而決定產(chǎn)生多少個(gè)實(shí)體任務(wù)或子流程。
如實(shí)現(xiàn)子流程多實(shí)例的獲取人數(shù),,則來(lái)自:
- /**
- * 獲取多實(shí)體子流程的執(zhí)行用戶集合
- * @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;
- }
因?yàn)樵摲椒〞?huì)被調(diào)用多次,,所以其實(shí)現(xiàn)的思路是第一次其集合是來(lái)自用戶的界面選擇的人員列表,第一次之后,,放到流程變量中去,,在后續(xù)的獲取中,直接從流程變量中獲取,。
然后在任務(wù)的創(chuàng)建的監(jiān)聽器中,,從流程變量assignee中獲取當(dāng)前任務(wù)的執(zhí)行人,。以上的實(shí)現(xiàn)還有一細(xì)節(jié)就是要解決如何查找到子流程中的第一個(gè)任務(wù)節(jié)點(diǎn),并且把對(duì)應(yīng)的任務(wù)人員授給這任務(wù)節(jié)點(diǎn),。
最終實(shí)現(xiàn)的效果如下所示:
http://www./htsite/html/cpjfw/zxjc/bpmx3/2012/08/27/1346037096478.html
|