flowable 之驳回 多实例驳回 并行网关驳回 普通节点驳回到多实例
flowable 驳回
欢迎大家学习交流,如有不对的地方,请大家多多指教,我接下来会把flowable的所有的中国式API*都写出来,也希望对大家有帮助,程序员只要静下心来,其实可以产生巨大的能量,靠任何人都没有用,唯有靠自己。学习好一门技术,还是多看看源代码,多在实际工作中用,如果想走捷径,想通过一本书或者一些视频想学好,那永远是痴心说梦。*
网上搜索了很多关于activiti的驳回方法,flowable的驳回方法,发现一个问题,基本都是在扯淡,根本无法解决商业用途,为了把这块吃透,我最近研究了一下他们的源代码,已在我们公司使用,暂时没有发现问题。其实看flowable的源代码很简单的,就是一个命令模式,仿照他们的命令模式写自己的就可以了,没有太大的难度。不得不佩服flowable的作者,用命令模式规范了自己的代码,而且把这么好的东西开源出来,从来没有找我们要过钱,这是何等的伟大,像大神致敬。闲话不多说,直接来代码比较干脆。
由于我们公司的流程有规范,所以有写地方有点特殊,如果不懂的可以随时给我留言即可,来也网络,去也网络。
- 1. 判断该节点上一个节点是不是并行网关节点
- 2. 如果上一个节点是提交者的话要处理一下
- 3. 添加审批意见和修改流程状态
- 4. 删除现有的所有任务
- 5. 删除节点信息
- 6. 驳回到disk节点
- 6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例
- 6.2 处理并行网关的多实例
具体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | @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 这个方法是添加审批意见和更新流程状态,由于流程状态没有,我这里扩展了一张表,状态主要有审批中,驳回,暂存,转办,撤回,终止等等状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /** * 添加审批意见和修改流程状态 * @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 删除任务命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 添加一个流程实例下面的执行实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 删除执行实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 执行跳转
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 ; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具