flowable 之驳回 多实例驳回 并行网关驳回 普通节点驳回到多实例
flowable 驳回
欢迎大家学习交流,如有不对的地方,请大家多多指教,我接下来会把flowable的所有的中国式API*都写出来,也希望对大家有帮助,程序员只要静下心来,其实可以产生巨大的能量,靠任何人都没有用,唯有靠自己。学习好一门技术,还是多看看源代码,多在实际工作中用,如果想走捷径,想通过一本书或者一些视频想学好,那永远是痴心说梦。*
网上搜索了很多关于activiti的驳回方法,flowable的驳回方法,发现一个问题,基本都是在扯淡,根本无法解决商业用途,为了把这块吃透,我最近研究了一下他们的源代码,已在我们公司使用,暂时没有发现问题。其实看flowable的源代码很简单的,就是一个命令模式,仿照他们的命令模式写自己的就可以了,没有太大的难度。不得不佩服flowable的作者,用命令模式规范了自己的代码,而且把这么好的东西开源出来,从来没有找我们要过钱,这是何等的伟大,像大神致敬。闲话不多说,直接来代码比较干脆。
由于我们公司的流程有规范,所以有写地方有点特殊,如果不懂的可以随时给我留言即可,来也网络,去也网络。
- 1. 判断该节点上一个节点是不是并行网关节点
- 2. 如果上一个节点是提交者的话要处理一下
- 3. 添加审批意见和修改流程状态
- 4. 删除现有的所有任务
- 5. 删除节点信息
- 6. 驳回到disk节点
- 6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例
- 6.2 处理并行网关的多实例
具体代码
public ReturnVo<String> backToStep(BackVo backVo) { ReturnVo<String> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK"); if (backVo != null && StringUtils.isNotBlank(backVo.getTaskId())) { TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(backVo.getTaskId()).singleResult(); if (taskEntity != null){ Activity distActivity = processDefinitionUtils.findFlowElementById(taskEntity.getProcessDefinitionId(), backVo.getDistFlowElementId()); if (taskEntity != null && distActivity != null) { //1. 判断该节点上一个节点是不是并行网关节点 List<SequenceFlow> incomingFlows = distActivity.getIncomingFlows(); if (CollectionUtils.isNotEmpty(incomingFlows)) { for (SequenceFlow sequenceFlow : incomingFlows) { FlowElement upNode = sequenceFlow.getSourceFlowElement(); if (upNode != null && (upNode instanceof ParallelGateway || upNode instanceof InclusiveGateway)) { returnVo = new ReturnVo<>(ReturnCode.FAIL, "并行节点无法驳回,请选择其他节点!"); return returnVo; } } } //2. 如果上一个节点是提交者的话要处理一下 if (FlowConstant.FLOW_SUBMITTER.equals(distActivity.getName())) { //查找发起人 ExtendHisprocinst extendHisprocinst = this.extendHisprocinstService.findExtendHisprocinstByProcessInstanceId(taskEntity.getProcessInstanceId()); if (extendHisprocinst != null) { runtimeService.setVariable(taskEntity.getProcessInstanceId(), FlowConstant.FLOW_SUBMITTER, extendHisprocinst.getCreator()); } } //3. 添加审批意见和修改流程状态 this.addCommentAndUpdateProcessStatus(backVo); //4. 删除现有的所有任务 managementService.executeCommand(new DeleteTaskCmd(taskEntity.getProcessInstanceId())); //5. 删除节点信息 this.deleteHisActivities(distActivity, taskEntity.getProcessInstanceId()); //6. 驳回到disk节点 Activity currActivity = processDefinitionUtils.findFlowElementById(taskEntity.getProcessDefinitionId(), taskEntity.getTaskDefinitionKey()); //6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例 boolean flag = false; if (currActivity.getBehavior() instanceof MultiInstanceActivityBehavior){ ExecutionEntity executionEntity = (ExecutionEntity)runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult(); managementService.executeCommand(new DeleteMultiInstanceExecutionCmd(executionEntity.getParentId(),false)); flag = true; } //6.2 处理并行网关的多实例 List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list(); if (CollectionUtils.isNotEmpty(executions) && executions.size() >1){ executions.forEach(execution -> { ExecutionEntity e = (ExecutionEntity)execution; managementService.executeCommand(new DeleteChildExecutionCmd(e)); }); flag = true; } if (flag) { ExecutionEntity parentExecutionEntity = (ExecutionEntity)runtimeService.createExecutionQuery().executionId(taskEntity.getProcessInstanceId()).singleResult(); managementService.executeCommand(new AddChildExecutionCmd(parentExecutionEntity)); } managementService.executeCommand(new JumpActivityCmd(taskEntity.getProcessInstanceId(),distActivity.getId())); //TODO 7. 处理加签的数据0 } }else { returnVo = new ReturnVo<>(ReturnCode.FAIL, "当前任务不存在!"); } } else { returnVo = new ReturnVo<>(ReturnCode.FAIL, "请设置相关参数!"); } return returnVo; }
- ProcessDefinitionUtils
@Component public class ProcessDefinitionUtils { @Autowired private RepositoryService repositoryService; /** * 获取end节点 * * @param processDefId * @return FlowElement */ public FlowElement findEndFlowElement(String processDefId) { Process process = repositoryService.getBpmnModel(processDefId).getMainProcess(); Collection<FlowElement> list = process.getFlowElements(); for (FlowElement f : list) { if (f instanceof EndEvent) { return f; } } return null; } /** * 获取指定节点的节点信息 * * @param processDefId * @param flowElementId * @return FlowElement */ public Activity findFlowElementById(String processDefId, String flowElementId) { Process process = repositoryService.getBpmnModel(processDefId).getMainProcess(); return (Activity) process.getFlowElement(flowElementId); } }
addCommentAndUpdateProcessStatus 这个方法是添加审批意见和更新流程状态,由于流程状态没有,我这里扩展了一张表,状态主要有审批中,驳回,暂存,转办,撤回,终止等等状态
/** * 添加审批意见和修改流程状态 * @param baseProcessVo 基本流程任务参数 */ protected void addCommentAndUpdateProcessStatus(BaseProcessVo baseProcessVo) { //兼容处理 if (StringUtils.isBlank(baseProcessVo.getProcessInstanceId())){ Task task = taskService.createTaskQuery().taskId(baseProcessVo.getTaskId()).singleResult(); if (task != null) { baseProcessVo.setProcessInstanceId(task.getProcessInstanceId()); } } //1.添加审批意见 FlowCommentVo flowCommentVo = new FlowCommentVo(baseProcessVo.getTaskId(), baseProcessVo.getUserCode(), baseProcessVo.getProcessInstanceId(), baseProcessVo.getMessage(), baseProcessVo.getCommentTypeEnum().toString()); this.addFlowComment(flowCommentVo); //2.修改流程实例的状态 ExtendHisprocinst extendHisprocinst = new ExtendHisprocinst(baseProcessVo.getProcessInstanceId(), baseProcessVo.getProcessStatusEnum().toString()); extendHisprocinstService.updateStatusByProcessInstanceId(extendHisprocinst); //3.TODO 生成索引 } /** * 添加审批意见 * @param flowCommentVo */ private void addFlowComment(FlowCommentVo flowCommentVo) { FlowCommentCmd cmd = new FlowCommentCmd(flowCommentVo.getTaskId(), flowCommentVo.getUserId(), flowCommentVo.getProcessInstanceId(), flowCommentVo.getType(), flowCommentVo.getMessage()); managementService.executeCommand(cmd); }
DeleteTaskCmd 删除任务命令
public class DeleteTaskCmd implements Command<Void> { private String processInstanceId; public DeleteTaskCmd(String processInstanceId) { this.processInstanceId = processInstanceId; } @Override public Void execute(CommandContext commandContext) { TaskEntityManager taskEntityManager = CommandContextUtil.getTaskEntityManager(commandContext); ExecutionEntityManager executionEntityManager = org.flowable.engine.impl.util.CommandContextUtil.getExecutionEntityManager(commandContext); List<ExecutionEntity> executionEntities = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId); executionEntities.forEach(executionEntity -> taskEntityManager.deleteTasksByExecutionId(executionEntity.getId())); return null; } }
AddChildExecutionCmd 添加一个流程实例下面的执行实例
public class AddChildExecutionCmd implements Command<Void> { private ExecutionEntity parentExecutionEntity; public AddChildExecutionCmd(ExecutionEntity parentExecutionEntity) { this.parentExecutionEntity = parentExecutionEntity; } @Override public Void execute(CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); executionEntityManager.createChildExecution(parentExecutionEntity); return null; } }
DeleteChildExecutionCmd 删除执行实例
public class DeleteChildExecutionCmd implements Command<Void> { private ExecutionEntity child; public DeleteChildExecutionCmd(ExecutionEntity child) { this.child = child; } @Override public Void execute(CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); executionEntityManager.delete(child,true); return null; } }
JumpActivityCmd 执行跳转
public class JumpActivityCmd implements Command<Void> { private String target; private String processInstanceId; public JumpActivityCmd(String processInstanceId, String target) { this.processInstanceId = processInstanceId; this.target = target; } @Override public Void execute(CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); List<ExecutionEntity> executionEntities = executionEntityManager.findChildExecutionsByParentExecutionId(processInstanceId); Process process = ProcessDefinitionUtil.getProcess(executionEntities.get(0).getProcessDefinitionId()); FlowNode targetFlowElement = (FlowNode) process.getFlowElement(target); FlowableEngineAgenda agenda = CommandContextUtil.getAgenda(); executionEntities.forEach(execution -> { execution.setCurrentFlowElement(targetFlowElement); agenda.planContinueProcessInCompensation(execution); }); return null; }