转载出处来自分享牛http://blog.csdn.net/qq_30739519)
Activiti多实例任务有并行、串行区分。
并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响。
串行代表工作或任务由一个人完成后,再由另一个人去处理,直至全部完成,每个任务依赖于前一个任务完成。
我们在使用activiti 工作流引擎的时候,最常用的肯定是任务节点,因为在OA系统、审批系统、办公自动化系统中核心的处理就是流程的运转,在流程运转的时候,可能我们有这样的一个需求,在一个任务节点的时候,我们需要多个人对这个节点进行审批,比如实际中这样一个例子,假如是一个部门的投票,这个部门有5个人,那么当5个人都投票的时候大概分为如下几种:
1.部门所有人都去投票,当所有人都投票完成的时候,这个节点结束,流程运转到下一个节点。(所有的人都需要投票)
2.部门所有人都去投票,只要有任意2/3的人同意,这个节点结束,流程运转到下一个节点。(部分人投票只要满足条件就算完成)。
3.部门中有一个部门经理,只要部门经理投票过了,这个节点结束,流程运转到下一个节点(一票否决权)。
4.部门中根据职位不同,不同的人都不同的权重,当满足条件的时候,这个节点结束,流程运转到下一个节点。比如说所有的人员权重加起来是1,a有0.2的权重,其他的四个人分别是0.1的权重,我们可以配置权重达到0.3就可以走向下一个节点,换言之a的权重是其他人的2倍,那就是a的投票相当于2个人投票。这种需求还是很常见的。
5.部门所有人都去投票,a投票结束到b,b开始投票结束到c,一直如此,串行执行。最终到最后一个人再统计结果,决定流程的运转。
上面的五种情况,我们可以提取出来一些信息,我们的activiti 工作流引擎,必须支持如下功能,才能满足上面的需求:
1.任务节点可以配置自定义满足条件。
2.任务节点必须支持串行、并行。
3.任务节点必须支持可以指定候选人或者候选组。
4.任务节点必须支持可以循环的次数。
5.任务节点必须支持可以自定义权重。
6.任务节点必须支持加签、减签。(就是动态的修改任务节点的处理人)
因为实际上的需求可能比上面的几种情况更加的复杂,上面的6个满足条件,工作流支持前4个,后面的2个条件是不支持的,所以我们必须要扩展activiti 工作流引擎才能使用5、6等的功能。下面我们将详细的介绍前四种条件的使用,在掌握基本使用之后,我们在后面的章节中将详细的介绍,5、6这两种功能以及可能更加复杂的操作。
为了演示如何使用,我们采用由浅入深的使用,结合流程图、流程定义xml、以及代码和数据库的变化来阐释每一个配置的使用以及含义。
流程的详细定义如下图所示:
流程的详细定义xml如下所示:
xml配置文件的部分含义如下:
1.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。
2.
3.
1.1.2.1. 串行的配置
修改
1.1.2.1.1. 流程的部署
Deployment deploy = repositoryService2.createDeployment()
.category(category).addClasspathResource("demo1.bpmn").deploy();
1.1.2.1.2. 流程的启动
/**
*
* @param runtimeService
* @param key
* act_re_procdef表的Id
* @param businessKey
* 业务单号
* @return
*/
public ProcessInstance startProcessInstanceByKey(
RuntimeService runtimeService, String key, String businessKey) {
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(key, businessKey);
return processInstance;
}
我们按照上面的步骤启动一个流程看一下数据库的变化。
ACT_RU_TASK表的数据有了如下图所示:
ACT_RU_IDENTITYLINK表的数据有了如下图所示:
ACT_RU_IDENTITYLINK权限表中,确实把我们设置的人员信息设置进去了,shareniu1,shareniu2,shareniu3,shareniu4现在就有代办信息了。
ACT_RU_VARIABLE表的数据有了如下图所示:
上面重要的变量需要解释一下,要不然还真不好理解,多任务是怎么运转的。
1.nrOfInstances 实例总数。
2.nrOfCompletedInstances 当前还没有完成的实例 nr是number单词缩写 。
3.loopCounter 已经循环的次数。
4.nrOfActiveInstances 已经完成的实例个数。
下面我们结束一个任务看一下,流程走到那个节点了。
1.1.2.1.3. 完成任务
String taskId="45009";
demo.getTaskService().complete(taskId);
接下来看一下数据库表的变化。
ACT_RU_VARIABLE表的数据有了如下图所示:
上面我们仔细的发现,可以看到
nrOfCompletedInstances、loopCounter、nrOfActiveInstances都加1了,确实多任务就是参考这几个值的变化进行判断的。
因为我们设置了循环2次,所以我们看看ACT_RU_IDENTITYLINK还有一个任务,因为我们是并行处理的。
所以我们在结束新的任务看一下流程是不是真的结束了,如果结束了,那么我们循环次数的配置就是正确的。
1.1.2.1.4. 完成任务
String taskId="47502";
demo.getTaskService().complete(taskId);
下面看一下ACT_RU_TASK,里面没有任务信息了,所以侧面证明循环次数的配置就是正确的。
接下来我们测试并行任务。除了isSequential="false",其他的配置是一样的。
1.1.2.2. 并行的配置测试
除了isSequential="false",其他的配置跟上面的串行是一样一样的。
重新部署测试,部署后我们启动一个新的流程测试。
ACT_RU_TASK表如下:
一次性的有2个任务需要处理,因为我们循环的是2次,所以直接就是2个。
ok串行、并行就讲解到这里。
我们配置的是循环2次,看以看到不管是并行还是串行,两个代办任务结束之后,流程直接跳转到下一个状态,但是
我们并没有配置结束条件,所以上面的例子,也可以看出来,如果不配置默认的通过条件,则默认条件是1,后面的源码章节会给大家说明这一点的。
在上面的串行、并行实例中,我们没有设置通过条件,但是程序按照配置的循环的次数,然后跳转到了下一个状态,可以侧面印证,如果不配置通过条件则默认值就是1.
下面的代码详细的介绍通过条件的配置,具体的配置代码如下:
1.1.4.1. 配置描述
nrOfCompletedInstances、nrOfInstances 变量描述上面已经描述了,我们这里设置的条件是大于1/4的人完成任务,任务就结束了。下面我们代码部署流程,启动流程后进行测试:
ACT_RU_TASK表如下:
我们随便结束一个任务,看一下ACT_RU_TASK表变化。
String taskId="60038";
demo.getTaskService().complete(taskId);
执行上面的代码,我们很神奇的发现,ACT_RU_TASK表中的其他任务没有了,因为我们配置了4个人,通过条件是1/4,所以任意一个人结束了,流程就结束了。这里我们测试的是并行,串行也是一样的,读者可以自行测试验证。
上面的几种方式,我们定义xml的时候,循环的次数是固定写在xml中的,也就是说我们配置的是循环2次,那么所有的流程实例都是循环2次,这样就不灵活了,程序当然是灵活了比较好,所以在实际开发中,我们可以使用下面的这种方式操作,使程序更加的灵活。
程序的xml配置如下所示:
动态配置如下所示:
参数说明:
activiti:assignee="${assignee}"
activiti:elementVariable="assignee" 多实例任务依赖上面的配置${assignee}
activiti:collection="assigneeList"
三个参数结合决定了,当前节点的处理人来自assigneeList集合,注意这里是集合信息而不是字符串,所以程序的运行时候变量的赋值,如下所示:
String[]v={"shareniu1","shareniu2","shareniu3","shareniu4"};
vars.put("assigneeList", Arrays.asList(v));
String taskId="97515";
demo.getTaskService().complete(taskId,vars);
ok了,测试一下,确实程序如预期的所示,大功告成。
参数的使用总结
4.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。
5.
6.
7.
这里我们还可以得出一个结论:
如果使用串行方式操作nrOfActiveInstances 变量始终是1,因为并行的时候才会去+1操作