多实例节点就是这个节点需要多个人审批,也就是会签,或签等,多个人可以按顺序审批,也可以同时审批。
首先创建一个多实例任务
public static UserTask createMultiUserTask(String id, String name,Integer count) {
UserTask userTask = new UserTask();
userTask.setName(name);
userTask.setId(id);
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
//节点完成条件 nrOfCompletedInstances完成数=nrOfInstances总数表示全部人完成节点才算完成
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==nrOfInstances}");
//是否按顺序执行
multiInstanceLoopCharacteristics.setSequential(false);
//Element variable设置为集合中变量名称,Element variable与Assignee的表达式变量是关联的
multiInstanceLoopCharacteristics.setElementVariable("assignee");
//Element variable与Collection的关系时单体与集合的关系。
//因此这个流程需要设置多实例任务的Assignee时,我们实际上需要传入流程变量assigneeList。
multiInstanceLoopCharacteristics.setInputDataItem("assigneeList");
//循环count次后方可提交
multiInstanceLoopCharacteristics.setLoopCardinality(count.toString());
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
userTask.setAssignee("${assignee}");
return userTask;
}
然后创建一个流程并部署
BpmnModel bpmnModel = new BpmnModel();
Process process = new Process();
bpmnModel.addProcess(process);
process.addFlowElement(EventEntity.createStartEvent("start","开始节点"));
process.addFlowElement(EventEntity.createServiceTask("cc1","抄送1"));
process.addFlowElement(EventEntity.createUserTask("user","用户任务","youshao"));
process.addFlowElement(EventEntity.createMultiUserTask("mul","多实例任务",3));
process.addFlowElement(EventEntity.createEndEvent("end","结束节点"));
process.addFlowElement(EventEntity.createSequence("start","cc1"));
process.addFlowElement(EventEntity.createSequence("cc1","user"));
process.addFlowElement(EventEntity.createSequence("user","mul"));
process.addFlowElement(EventEntity.createSequence("mul","end"));
process.setId("weige");
process.setName("伟哥的升职流程");
//校验流程准确性
ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
ProcessValidator processValidator = processValidatorFactory.createDefaultProcessValidator();
List<ValidationError> validate = processValidator.validate(bpmnModel);
if(validate.size()>=1){
for (ValidationError validationError : validate) {
System.out.println(validationError.getProblem());
System.out.println(validationError.isWarning());
}
}
//流程部署
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
Deployment deploy = deploymentBuilder
.addBpmnModel("test.bpmn", bpmnModel)
.name("名称名称")
.deploy();
String deployId = deploy.getId();
System.out.println("流程部署id: "+deployId);
启动流程实例
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
String key = processDefinition.getKey();
System.out.println("key:"+key);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
System.out.println("--------流程实例------");
System.out.println("ProcessInstanceId:"+processInstance.getProcessInstanceId());
System.out.println("ProcessDefinitionId:"+processInstance.getProcessDefinitionId());
System.out.println("isEnded"+processInstance.isEnded());
System.out.println("isSuspended:"+processInstance.isSuspended());
//实例任务
List<Task> list = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
for(Task tk : list){
System.out.println("Id:"+tk.getId());
System.out.println("Name:"+tk.getName());
System.out.println("Assignee:"+tk.getAssignee());
}
完成第一个用户节点任务 并设置多实例节点的执行人
//待办任务
List<Task> taskList = taskService.createTaskQuery()
.taskAssignee("youshao")
.list();
for(Task tk : taskList){
System.out.println("Id:"+tk.getId());
System.out.println("Name:"+tk.getName());
System.out.println("Assignee:"+tk.getAssignee());
}
//完成任务
Map<String ,Object> variables = new HashMap<>();
variables.put("assigneeList", Arrays.asList("weige","yixiong","suren"));
taskService.complete(taskList.get(0).getId(),variables);
下面是刚才的输出
14:32:04.191 o.a.e.impl.bpmn.deployer.BpmnDeployer : Process deployed: {id: weige:1:3b27f727-5b41-11ed-aafa-040e3c277f39, key: weige, name: 伟哥的升职流程 }
流程部署id: 3b0d9155-5b41-11ed-aafa-040e3c277f39
------流程定义--------
Name:伟哥的升职流程
Key:weige
ResourceName:test.bpmn
DeploymentId:3b0d9155-5b41-11ed-aafa-040e3c277f39
Version:1
key:weige
14:32:55.267 com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=55s764ms819µs).
-------------------------------------- taskService 执行了 ------------------------------------
--------流程实例------
ProcessInstanceId:472ff3b8-5b41-11ed-aafa-040e3c277f39
ProcessDefinitionId:weige:1:3b27f727-5b41-11ed-aafa-040e3c277f39
isEndedfalse
isSuspended:false
Id:64b3cc9d-5b41-11ed-aafa-040e3c277f39
Name:用户任务
Assignee:youshao
14:33:45.410 com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=50s143ms767µs700ns).
Id:64b3cc9d-5b41-11ed-aafa-040e3c277f39
Name:用户任务
Assignee:youshao
这时已经执行到了多实例任务节点
执行实例表有了5条数据,第一条是流程实例,第二条主执行实例,3-5条分别为多实例的三个执行实例
任务表有三条任务
接下来看下变量表,注意一下nrOfCompletedInstances和nrOfInstances的值,现在nrOfInstances为3,nrOfCompletedInstances为0
现在执行多实例的其中一个任务
taskService.complete("7ecb2e97-5b41-11ed-aafa-040e3c277f39");//taskId直接从表里复制的
任务表现在只有两条任务了
执行实例表的一列数据的is_active变为了0,当全部变为0时,从ru表移除。
并且变量表的nrOfCompletedInstances=1,nrOfInstances=2,表示已经完成了一个实例
当达到CompletionCondition的完成条件时(这次我设置的nrOfCompletedInstances==nrOfInstances,也就是全部实例完成,可以根据需求设为半数完成即完成),该节点完成。