首先,在activiti中,是无法实现在当前流程实例中动态增加一个节点而不影响其它实例的,也就是真正意义上的加签。(网上现有的所谓的加签是直接修改了bpmn的定义,这样一来会影响到所有流程实例)。那么如果我们想动态加签,怎么办呢?
Activiti官方是支持会签的,所谓会签,就是多人来签核同一个任务,在activiti中是通过节点多实例来实现的。但是通过节点多实例来设置会签人员必须在这个节点的之前的节点中设置好才行,而不能到了这个节点后,动态增加签核的人了。
但是现在公司的有这种动态增加会签人员的需求,我自己想了下,貌似是可以实现的,实现思路:
- 到了多实例节点这一步时,取得该节点的流程变量,即之前节点设好的会签人员list
- 改变会签人员list,增加人员
- 重新设置流程变量为最新的会签人员list
- 让流程引擎将上述改动生效
上述实现乍一看没什么问题,但实际写代码时发现,1-3步都可以实现,但是流程引擎不会将这些改动生效,而且我发现还有一个问题是新增的人在任务列表里是看不见任务的。所以还需要动态增加一个该节点的实例。
于是按这个思路在网上找了下相关的内容,经过借鉴来改进,终于实现了会签节点的动态加签。不多说,直接上代码。
package com.zp.activitispringboot.cmd; import org.activiti.bpmn.model.Activity; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics; import org.activiti.bpmn.model.UserTask; import org.activiti.engine.ActivitiException; import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; import org.activiti.engine.impl.history.HistoryManager; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.TaskEntityManager; import org.activiti.engine.impl.util.ProcessDefinitionUtil; public class AddMultiInstanceCmd implements Command { protected final String NUMBER_OF_INSTANCES = "nrOfInstances"; protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances"; private String taskId; private String addUserTaskAssign; public AddMultiInstanceCmd(String taskId, String addUserTaskAssign) { this.taskId = taskId; this.addUserTaskAssign = addUserTaskAssign; } @Override public Object execute(CommandContext commandContext) { TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager(); ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager(); //根据任务id获取任务实例 TaskEntity taskEntity = taskEntityManager.findById(taskId); //根据执行实例ID获取当前执行实例 ExecutionEntity multiExecutionEntity = executionEntityManager.findById(taskEntity.getExecutionId()); // 获取流程执行实例(即当前执行实例的父实例) ExecutionEntity parentExecutionEntity = multiExecutionEntity.getParent(); //判断当前执行实例的节点是否是多实例节点 BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(multiExecutionEntity.getProcessDefinitionId()); Activity miActivityElement = (Activity) bpmnModel.getFlowElement(multiExecutionEntity.getCurrentActivityId()); MultiInstanceLoopCharacteristics loopCharacteristics = miActivityElement.getLoopCharacteristics(); if(loopCharacteristics == null){ throw new ActivitiException("此节点不是多实例节点"); } //判断是否是并行多实例 if(loopCharacteristics.isSequential()){ throw new ActivitiException("此节点为串行节点"); } //创建新的子实例 ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity); //获取并为新的执行实例设置当前活动节点 UserTask currentFlowElement = (UserTask) multiExecutionEntity.getCurrentFlowElement(); //设置处理人 currentFlowElement.setAssignee(addUserTaskAssign); childExecution.setCurrentFlowElement(currentFlowElement); //获取设置变量 Integer nrOfInstances = (Integer) parentExecutionEntity.getVariableLocal(NUMBER_OF_INSTANCES); Integer nrOfActiveInstances = (Integer) parentExecutionEntity.getVariableLocal(NUMBER_OF_ACTIVE_INSTANCES); parentExecutionEntity.setVariableLocal(NUMBER_OF_INSTANCES,nrOfInstances+1); parentExecutionEntity.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances+1); //通知活动开始 HistoryManager historyManager = commandContext.getHistoryManager(); historyManager.recordActivityStart(childExecution); //获取处理行为类 ParallelMultiInstanceBehavior prallelMultiInstanceBehavior = (ParallelMultiInstanceBehavior) miActivityElement.getBehavior(); AbstractBpmnActivityBehavior innerActivityBehavior = prallelMultiInstanceBehavior.getInnerActivityBehavior(); //执行 innerActivityBehavior.execute(childExecution); return null; } }