上篇博文,咱们完成一个任务SKIP的实现,说好要给各位看官带来驳回实现的如今,就奉上具体实现和讲解。(其实我感受个人注释写的已经很是清楚了,哈哈)java
依旧是,先说咱们的需求和思路。web
PS:数据库
从6.0.0降到5.22.0版本的缘由由于项目中有一个版本冲突,致使的降级。后期仍是以新版本为主。6.0版本的驳回有时间再来搞。ide
需求:测试
嗯,大体上就是这样的一个需求,根据这个需求,其实我走了不少弯路,但都离不开两点。this
思路:日志
1. 将当前的任务节点的下一个任务节点指定为指定的驳回任务节点 2. 将指定任务(目标任务)节点以后的流程轨迹,清空。
根据这个思路,我追了源码,看了各类Service,Manager等等。由于别人的驳回流程我拿下来发现是有错的,因此就本身研究了起来。如今就直接上代码吧。呸。先上图,没图谁会信你成功了呢?code
嗯 上面 就是一个测试过程,主要想表达一个意思:当前流程实例中的任务驳回以后,不影响别的流程实例。这里有一张以前研究时的错误图,能够给你们看看。不喷哈~~排序
好了下面上代码~~~~get
代码:
每个region endregion是一个代码块。在IDEA中是能够折叠的。C#中的习惯吧算是 能让代码更好看些。。。。(我的认为)
/** * 驳回任务方封装 * * @param destinationTaskID 驳回的任务ID 目标任务ID * @param messageContent 驳回的理由 * @param currentTaskID 当前正要执行的任务ID * @return 驳回结果 携带下个任务编号 */ public ResponseResult rejectTask(String destinationTaskID, String currentTaskID, String messageContent) { // region 目标任务实例 historicDestinationTaskInstance 带流程变量,任务变量 HistoricTaskInstance historicDestinationTaskInstance = historyService .createHistoricTaskInstanceQuery() .taskId(destinationTaskID) .includeProcessVariables() .includeTaskLocalVariables() .singleResult(); // endregion // region 正在执行的任务实例 historicCurrentTaskInstance 带流程变量,任务变量 HistoricTaskInstance historicCurrentTaskInstance = historyService .createHistoricTaskInstanceQuery() .taskId(currentTaskID) .includeProcessVariables() .includeTaskLocalVariables() .singleResult(); // endregion // 流程定义ID String processDefinitionId = historicCurrentTaskInstance.getProcessDefinitionId(); // 流程实例ID String processInstanceId = historicCurrentTaskInstance.getProcessInstanceId(); // 流程定义实体 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); // region 根据任务建立时间正序排序获取历史任务实例集合 historicTaskInstanceList 含流程变量,任务变量 List<HistoricTaskInstance> historicTaskInstanceList = historyService .createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .includeProcessVariables() .includeTaskLocalVariables() .orderByTaskCreateTime() .asc() .list(); // endregion // region 历史活动节点实例集合 historicActivityInstanceList List<HistoricActivityInstance> historicActivityInstanceList = historyService .createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .asc() .list(); // endregion // 获取目标任务的节点信息 ActivityImpl destinationActivity = processDefinition .findActivity(historicDestinationTaskInstance.getTaskDefinitionKey()); // 定义一个历史任务集合,完成任务后任务删除此集合中的任务 List<HistoricTaskInstance> deleteHistoricTaskInstanceList = new ArrayList<>(); // 定义一个历史活动节点集合,完成任务后要添加的历史活动节点集合 List<HistoricActivityInstanceEntity> insertHistoricTaskActivityInstanceList = new ArrayList<>(); // 目标任务编号 Integer destinationTaskInstanceId = Integer.valueOf(destinationTaskID); // 有序 for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) { Integer historicTaskInstanceId = Integer.valueOf(historicTaskInstance.getId()); if (destinationTaskInstanceId <= historicTaskInstanceId) { deleteHistoricTaskInstanceList.add(historicTaskInstance); } } // 有序 for (int i = 0; i < historicActivityInstanceList.size() - 1; i++) { HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i); // 历史活动节点的任务编号 Integer historicActivityInstanceTaskId; String taskId = historicActivityInstance.getTaskId(); if (taskId != null) { historicActivityInstanceTaskId = Integer.valueOf(taskId); if (historicActivityInstanceTaskId <= destinationTaskInstanceId) { insertHistoricTaskActivityInstanceList.add((HistoricActivityInstanceEntity) historicActivityInstance); } } else { if (historicActivityInstance.getActivityType().equals(ProcessConstant.START_EVENT)) { insertHistoricTaskActivityInstanceList.add((HistoricActivityInstanceEntity) historicActivityInstance); } else if (historicActivityInstance.getActivityType().equals(ProcessConstant.EXCLUSIVE_GATEWAY)) { insertHistoricTaskActivityInstanceList.add((HistoricActivityInstanceEntity) historicActivityInstance); } } } // 获取流程定义的节点信息 List<ActivityImpl> processDefinitionActivities = processDefinition.getActivities(); // 用于保存正在执行的任务节点信息 ActivityImpl currentActivity = null; // 用于保存原来的任务节点的出口信息 PvmTransition pvmTransition = null; // 保存原来的流程节点出口信息 for (ActivityImpl activity : processDefinitionActivities) { if (historicCurrentTaskInstance.getTaskDefinitionKey().equals(activity.getId())) { currentActivity = activity; // 备份 pvmTransition = activity.getOutgoingTransitions().get(0); // 清空当前任务节点的出口信息 activity.getOutgoingTransitions().clear(); } } // 执行流程转向 processEngine.getManagementService().executeCommand( new RejectTaskCMD(historicDestinationTaskInstance, historicCurrentTaskInstance, destinationActivity)); // 获取正在执行的任务的流程变量 Map<String, Object> taskLocalVariables = historicCurrentTaskInstance.getTaskLocalVariables(); // 获取目标任务的流程变量,修改任务不自动跳过,要求审批 Map<String, Object> processVariables = historicDestinationTaskInstance.getProcessVariables(); // 获取流程发起人编号 Integer employeeId = (Integer) processVariables.get(ProcessConstant.PROCESS_START_PERSON); processVariables.put(ProcessConstant.SKIP_EXPRESSION, false); taskLocalVariables.put(ProcessConstant.SKIP_EXPRESSION, false); // 设置驳回缘由 taskLocalVariables.put(ProcessConstant.REJECT_REASON, messageContent); // region 流程变量转换 // 修改下个任务的任务办理人 processVariables.put(ProcessConstant.DEAL_PERSON_ID, processVariables.get(ProcessConstant.CURRENT_PERSON_ID)); // 修改下个任务的任务办理人姓名 processVariables.put(ProcessConstant.DEAL_PERSON_NAME, processVariables.get(ProcessConstant.CURRENT_PERSON_NAME)); // 修改下个任务的任务办理人 taskLocalVariables.put(ProcessConstant.DEAL_PERSON_ID, processVariables.get(ProcessConstant.CURRENT_PERSON_ID)); // 修改下个任务的任务办理人姓名 taskLocalVariables.put(ProcessConstant.DEAL_PERSON_NAME, processVariables.get(ProcessConstant.CURRENT_PERSON_NAME)); // endregion // 完成当前任务,任务走向目标任务 String nextTaskId = processService.completeTaskByTaskID(currentTaskID, processVariables, taskLocalVariables); if (currentActivity != null) { // 清空临时转向信息 currentActivity.getOutgoingTransitions().clear(); } if (currentActivity != null) { // 恢复原来的走向 currentActivity.getOutgoingTransitions().add(pvmTransition); } // 删除历史任务 for (HistoricTaskInstance historicTaskInstance : deleteHistoricTaskInstanceList) { historyService.deleteHistoricTaskInstance(historicTaskInstance.getId()); } // 删除活动节点 processEngine.getManagementService().executeCommand( (Command<List<HistoricActivityInstanceEntity>>) commandContext -> { HistoricActivityInstanceEntityManager historicActivityInstanceEntityManager = commandContext.getHistoricActivityInstanceEntityManager(); // 删除全部的历史活动节点 historicActivityInstanceEntityManager .deleteHistoricActivityInstancesByProcessInstanceId(processInstanceId); // 提交到数据库 commandContext.getDbSqlSession().flush(); // 添加历史活动节点的 for (HistoricActivityInstanceEntity historicActivityInstance : insertHistoricTaskActivityInstanceList) { historicActivityInstanceEntityManager.insertHistoricActivityInstance(historicActivityInstance); } // 提交到数据库 commandContext.getDbSqlSession().flush(); return null; } ); // 返回下个任务的任务ID return ResponseResultUtil.success(nextTaskId); }
我本身都知道有很差的地方,可是别的方法我没有实现成功,因此先这样作吧。过年的时候再好好看看改改。
下面是RejectTaskCMD这个类的代码:
package com.edu.hart.web.manage.process; import org.activiti.engine.history.HistoricTaskInstance; 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.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.process.TransitionImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; /** * 任务驳回方法支持 * * @author create by 叶云轩 at 2018/1/15 09:32 */ public class RejectTaskCMD implements Command<Object>, Serializable { /** * RejectTaskCMD 日志控制器 * Create by 叶云轩 at 2018/1/19 09:43 * Concat at yCountJavaXuan@outlook.com */ private static final Logger LOGGER = LoggerFactory.getLogger(RejectTaskCMD.class); /** * 历史信息中的当前任务实例 */ private HistoricTaskInstance currentTaskInstance; /** * 历史信息中的目标任务实例 */ private HistoricTaskInstance destinationTaskInstance; /** * 目标任务节点 */ private ActivityImpl destinationActivity; /** * 构造方法 * * @param currentTaskInstance 当前任务实例 * @param destinationTaskInstance 目标任务实例 * @param destinationActivity 目标节点 */ public RejectTaskCMD(HistoricTaskInstance currentTaskInstance , HistoricTaskInstance destinationTaskInstance , ActivityImpl destinationActivity) { this.currentTaskInstance = currentTaskInstance; this.destinationTaskInstance = destinationTaskInstance; this.destinationActivity = destinationActivity; } @Override public Object execute(CommandContext commandContext) { // 流程实例ID String processInstanceId = destinationTaskInstance.getProcessInstanceId(); // 执行管理器 ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager(); // select * from ACT_RU_EXECUTION where ID_ = ? 查询当前流程实例中正在执行的惟一任务 --追源码时发现这个方法的做用,就记录了下来,省的本身遗忘掉 ExecutionEntity executionEntity = executionEntityManager.findExecutionById(processInstanceId); // 当前活跃的节点信息 ActivityImpl currentActivity = executionEntity.getActivity(); // 建立一个出口转向 TransitionImpl outgoingTransition = currentActivity.createOutgoingTransition(); // 封装目标节点到转向实体 outgoingTransition.setDestination(destinationActivity); // 流程转向 executionEntity.setTransition(outgoingTransition); return null; } }
嗯,就是这样来完成任意节点驳回的。当前先这样实现了,6.0版本没有了Pvm这些类,还须要再研究研究~~