Activiti 多个并发子流程的应用
应用场景:
?
?
多个部门发起资金计划,最后统一到财务部审批,每个部门发起资金计划是一个子流程,财务部审批是多个部门的计划同时审批,审批完成后,再提交上级领导审批。
?
流程如下:
?
要解决以上问题,需要实现多个子流程并行处理的功能。在Activiti5有一个比较强的节点属性就是多实例,它可以支持多实例的子流程,多实例任务,多实体脚本等。目前支持多实例的节点类型有:
?
- Java代码??
- <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>??
?
?
多实例子流程
?
Java代码?? - <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>??
?
所以关键的配置属性:
?
Java代码?? - <multiInstanceLoopCharacteristics??
- ????????activiti:elementVariable="assignee"?isSequential="false"??
- ????????activiti:collection="${taskUserAssignService.getSignUser(execution)}">??
- ????????<completionCondition>${signComplete.isComplete(execution)?}??
- ????????</completionCondition>??
- ????</multiInstanceLoopCharacteristics>??
?
我们在控制多实例的个数或人数时,是通过taskUserAssignService的getSignUser获取或getMultipleUser(execution)其集合的个数,从而决定产生多少个实体任务或子流程。
?
如实现子流程多实例的获取人数,则来自:
Java代码?? - /**?
- ?????*?获取多实体子流程的执行用户集合?
- ?????*?@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:1438712946
?电话:13070215345
最终实现的效果如下所示:
?
http://www.jee-soft.cn/htsite/html/cpjfw/zxjc/bpmx3/2012/08/27/1346037096478.html
