Activiti 多个并发子流程的应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activiti 多个并发子流程的应用相关的知识,希望对你有一定的参考价值。

应用场景:

 

 

多个部门发起资金计划,最后统一到财务部审批,每个部门发起资金计划是一个子流程,财务部审批是多个部门的计划同时审批,审批完成后,再提交上级领导审批。

 

流程如下:

技术分享图片

 

要解决以上问题,需要实现多个子流程并行处理的功能。在Activiti5有一个比较强的节点属性就是多实例,它可以支持多实例的子流程,多实例任务,多实体脚本等。目前支持多实例的节点类型有:

 

 

 

多实例还有并行、串行区分。以下解释一下什么是并行与串行

并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响。

串行代表工作或任务由一个人完成后,再由另一个人去处理,直至全部完成,每个任务依赖于前一个任务完成。

 

会签任务即可以由activiti多实例任务节点来实现,(上一博客有介绍如何开发设计会签任务)

 

在Activiti的定义中,生成多实例的定义很简单,只需要如下类似去生成以下标签,则可以完成多实例的声明,如下所示,我们要支持并行节点的多实例的定义

 

多实例人工任务

 

Java代码  技术分享图片

  1. <userTask activiti:assignee="${assignee}" id="SignTask2" name="财务主管会签">  

  2.     <extensionElements>  

  3.         <activiti:taskListener  

  4.             class="com.hotent.platform.service.bpm.listener.TaskSignCreateListener"  

  5.             event="create" />  

  6.         <activiti:taskListener  

  7.             class="com.hotent.platform.service.bpm.listener.TaskAssignListener"  

  8.             event="assignment" />  

  9.         <activiti:taskListener  

  10.             class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"  

  11.             event="complete" />  

  12.     </extensionElements>  

  13.     <multiInstanceLoopCharacteristics  

  14.         activiti:elementVariable="assignee" isSequential="false"  

  15.         activiti:collection="${taskUserAssignService.getSignUser(execution)}">  

  16.         <completionCondition>${signComplete.isComplete(execution) }  

  17.         </completionCondition>  

  18.     </multiInstanceLoopCharacteristics>  

  19. </userTask>  

 

 

多实例子流程

 

Java代码  技术分享图片

  1. <subProcess activiti:assignee="${assignee}" id="SubProcess1"  

  2.     name="部门资金计划流程">  

  3.     <startEvent activiti:initiator="startUser" id="startEvent2"  

  4.         name="开始" />  

  5.     <endEvent id="endEvent1" name="结束1" />  

  6.     <userTask id="task3" name="助理填写">  

  7.         <documentation />  

  8.         <extensionElements>  

  9.             <activiti:taskListener  

  10.                 class="com.hotent.platform.service.bpm.listener.TaskCreateListener"  

  11.                 event="create" />  

  12.             <activiti:taskListener  

  13.                 class="com.hotent.platform.service.bpm.listener.TaskAssignListener"  

  14.                 event="assignment" />  

  15.             <activiti:taskListener  

  16.                 class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"  

  17.                 event="complete" />  

  18.         </extensionElements>  

  19.     </userTask>  

  20.     <userTask id="task4" name="部门领导审查">  

  21.         <documentation />  

  22.         <extensionElements>  

  23.             <activiti:taskListener  

  24.                 class="com.hotent.platform.service.bpm.listener.TaskCreateListener"  

  25.                 event="create" />  

  26.             <activiti:taskListener  

  27.                 class="com.hotent.platform.service.bpm.listener.TaskAssignListener"  

  28.                 event="assignment" />  

  29.             <activiti:taskListener  

  30.                 class="com.hotent.platform.service.bpm.listener.TaskCompleteListener"  

  31.                 event="complete" />  

  32.         </extensionElements>  

  33.     </userTask>  

  34.     <sequenceFlow sourceRef="startEvent2" targetRef="task3"  

  35.         id="sequenceFlow1" name="" />  

  36.     <sequenceFlow sourceRef="task3" targetRef="task4" id="sequenceFlow2"  

  37.         name="" />  

  38.     <sequenceFlow sourceRef="task4" targetRef="endEvent1" id="sequenceFlow3"  

  39.         name="" />  

  40.     <extensionElements>  

  41.         <activiti:executionListener event="start"  

  42.             class="com.hotent.platform.service.bpm.listener.StartEventListener" />  

  43.         <activiti:executionListener event="end"  

  44.             class="com.hotent.platform.service.bpm.listener.EndEventListener" />  

  45.     </extensionElements>  

  46.     <multiInstanceLoopCharacteristics  

  47.         activiti:elementVariable="assignee" isSequential="false"  

  48.         activiti:collection="${taskUserAssignService.getMultipleUser(execution)}" />  

  49. </subProcess>  

 

所以关键的配置属性:

 

Java代码  技术分享图片

  1. <multiInstanceLoopCharacteristics  

  2.         activiti:elementVariable="assignee" isSequential="false"  

  3.         activiti:collection="${taskUserAssignService.getSignUser(execution)}">  

  4.         <completionCondition>${signComplete.isComplete(execution) }  

  5.         </completionCondition>  

  6.     </multiInstanceLoopCharacteristics>  

 

我们在控制多实例的个数或人数时,是通过taskUserAssignService的getSignUser获取或getMultipleUser(execution)其集合的个数,从而决定产生多少个实体任务或子流程。

 

如实现子流程多实例的获取人数,则来自:

Java代码  技术分享图片

  1. /** 

  2.      * 获取多实体子流程的执行用户集合 

  3.      * @param execution 

  4.      * @return 

  5.      * @throws Execption 

  6.      */  

  7.     public List<String> getMultipleUser(ActivityExecution execution) throws Exception{  

  8.           

  9.         String nodeId=execution.getActivity().getId();  

  10.         ExecutionEntity executionEnt=(ExecutionEntity) execution;  

  11.           

  12.         List<String> userIds=(List<String>)execution.getVariable(BpmConst.SUBPRO_MULTI_USERIDS);  

  13.           

  14.         if(userIds!=nullreturn userIds;  

  15.         Map<String,FlowNode> nodeMap= NodeCache.getByActDefId(executionEnt.getProcessDefinitionId());  

  16.         FlowNode subProcessNode=nodeMap.get(nodeId);  

  17.         FlowNode firstNode=subProcessNode.getSubFirstNode();  

  18.           

  19.         FlowNode secodeNode=firstNode.getNextFlowNodes().get(0);  

  20.           

  21.         List<String> userList=nodeUserMapLocal.get().get(secodeNode.getNodeId());  

  22.           

  23.         logger.debug("userList size:" + userList.size());  

  24.           

  25.         execution.setVariable(BpmConst.SUBPRO_MULTI_USERIDS, userList);  

  26.         return userList;  

  27.     }  

 

因为该方法会被调用多次,所以其实现的思路是第一次其集合是来自用户的界面选择的人员列表,第一次之后,放到流程变量中去,在后续的获取中,直接从流程变量中获取。

然后在任务的创建的监听器中,从流程变量assignee中获取当前任务的执行人。以上的实现还有一细节就是要解决如何查找到子流程中的第一个任务节点,并且把对应的任务人员授给这任务节点。

 

 

更多资讯请加QQ了解1361783075


以上是关于Activiti 多个并发子流程的应用的主要内容,如果未能解决你的问题,请参考以下文章

Activiti 学习—— Activiti 流程启动并完成

Activiti手动执行的应用(UserTask)

activiti自己定义流程之Spring整合activiti-modeler实例:启动流程

activiti5 流程里面怎么回退到上一个节点

Activiti应用实践-查询BPMN XML文件和图片资源文件

我activiti 部署流程 为啥有一个表没有插入数据