前言
Activiti 中有互斥网关和并行网关,但是在实际项目开发中,经常会出现一些看起来离奇的需求,比如任务分配给多人审批,只要指定数量的人审批通过就可以进入下一个流程。
流程图
部分XML
<userTask id="usertask1" name="会签(多人参与)" activiti:assignee="${assignee}">
<multiInstanceLoopCharacteristics
isSequential="false"
activiti:collection="assigneeList"
activiti:elementVariable="assignee">
<completionCondition>${nrOfCompletedInstances/nrOfInstances >=0.5}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
参数
- isSequential:串行并行的配置。
- Collection:存放集合,集合中可以存任意值,工作流会根据你集合里的值个数,去生成对应的子流程,例如:我这里存的是3个用户的ID,{1,2,3,4},那么就会生成出4个子流程。
- Element variable:节点流程变量,用于在流程图中代替集合中表示当前子流程的变量(我这存的是用户ID,所以表示的就是用户ID)。这个节点流程变量可以在当前task中使用。
- Completion condition:完成条件,这里写的表达式如果满足即可进入下一个流程,表达式:${nrOfCompletedInstances/nrOfInstances >=0.5}。
- nrOfInstances:实例总数
- nrOfActiveInstances:当前活动的实例数量,对于顺序执行的多实例,值一直为1。
- nrOfCompletedInstances:已经完成实例的数目。
- Main config 中 Assignee 参数 ${assignee},这里对应的是 Multi instance 中的 Element variable 参数。
伪代码
新增流程实例:
Map<String, Object> variables = new HashMap<String, Object>();
List<String> candiateUserList= Arrays.asList(new String[] {"1","2","3","4"});
variables.put("assigneeList", candiateUserList);
ProcessInstance in = runtimeService.startProcessInstanceByKey("counterSign", variables);
System.out.println("实例ID"+in.getId());
List<Task> list = taskService.createTaskQuery().processInstanceId(in.getId()).list();
System.out.println("任务数量:"+list.size());
list.forEach(task -> {
System.out.println("任务ID"+task.getId());
System.out.println("指派人ID"+task.getAssignee());
});
任务查询:
TaskQuery query = taskService.createTaskQuery();
List<Task> list = query.taskAssignee(userId).taskDefinitionKey("counterSign").list();
list.forEach(task -> {
System.out.println("任务ID"+task.getId());
});
处理任务:
//会签,满足两人以上即可,表达式:${nrOfCompletedInstances/nrOfInstances >=0.5}
taskService.claim(taskId, userId);
taskService.complete(taskId);
根据表达式,只要满足两人以上执行了此任务就会进入下一个流程。