歡迎你們學習交流,若有不對的地方,請你們多多指教,我接下來會把flowable的全部的中國式API*都寫出來,也但願對你們有幫助,程序員只要靜下心來,其實能夠產生巨大的能量,靠任何人都沒有用,惟有靠本身。學習好一門技術,仍是多看看源代碼,多在實際工做中用,若是想走捷徑,想經過一本書或者一些視頻想學好,那永遠是癡心說夢。*java
網上搜索了不少關於activiti的駁回方法,flowable的駁回方法,發現一個問題,基本都是在扯淡,根本沒法解決商業用途,爲了把這塊吃透,我最近研究了一下他們的源代碼,已在咱們公司使用,暫時沒有發現問題。其實看flowable的源代碼很簡單的,就是一個命令模式,仿照他們的命令模式寫本身的就能夠了,沒有太大的難度。不得不佩服flowable的做者,用命令模式規範了本身的代碼,並且把這麼好的東西開源出來,歷來沒有找咱們要過錢,這是何等的偉大,像大神致敬。閒話很少說,直接來代碼比較乾脆。程序員
因爲咱們公司的流程有規範,因此有寫地方有點特殊,若是不懂的能夠隨時給我留言便可,來也網絡,去也網絡。網絡
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; }
@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 這個方法是添加審批意見和更新流程狀態,因爲流程狀態沒有,我這裏擴展了一張表,狀態主要有審批中,駁回,暫存,轉辦,撤回,終止等等狀態ide
/** * 添加審批意見和修改流程狀態 * @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 添加一個流程實例下面的執行實例this
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 刪除執行實例spa
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; }