Activiti 5.22.0 之自由驳回任务实现(亲测)

上篇博文,咱们完成一个任务SKIP的实现,说好要给各位看官带来驳回实现的如今,就奉上具体实现和讲解。(其实我感受个人注释写的已经很是清楚了,哈哈)java

依旧是,先说咱们的需求和思路。web

PS:数据库

从6.0.0降到5.22.0版本的缘由由于项目中有一个版本冲突,致使的降级。后期仍是以新版本为主。6.0版本的驳回有时间再来搞。ide

需求:测试

  1. 流程中的审批任务节点能够驳回到以前的任意任务节点
  2. 驳回到指定节点的任务以后的轨迹不须要显示

嗯,大体上就是这样的一个需求,根据这个需求,其实我走了不少弯路,但都离不开两点。this

思路:日志

1. 将当前的任务节点的下一个任务节点指定为指定的驳回任务节点
2. 将指定任务(目标任务)节点以后的流程轨迹,清空。

点击并拖拽以移动

根据这个思路,我追了源码,看了各类Service,Manager等等。由于别人的驳回流程我拿下来发现是有错的,因此就本身研究了起来。如今就直接上代码吧。呸。先上图,没图谁会信你成功了呢?code

  1. 启动报销流程 返回的是下个任务编号

1.启动报销流程

  1. 启动后查询流程轨迹

2.启动后查询流程轨迹

  1. 查询流程中历史任务节点信息

3.查询流程中历史任务节点信息

  1. 驳回任务到指定任务节点

4.驳回任务到指定节点

  1. 驳回后查询流程轨迹图

5.驳回后查询

  1. 查询驳回的历史任务信息

6.查询驳回的历史任务信息

  1. 启动一个新的流程实例

7启动一个新的流程实例

  1. 查询新的流程实例的轨迹

8.查询新的流程实例的轨迹

  1. 完成新的流程实例任务,模拟审批经过

9.完成新的流程实例任务,模拟审批经过

  1. 查询新流程实例对应完成任务后的轨迹

10.查询新流程实例对应完成任务后的轨迹

嗯 上面 就是一个测试过程,主要想表达一个意思:当前流程实例中的任务驳回以后,不影响别的流程实例。这里有一张以前研究时的错误图,能够给你们看看。不喷哈~~排序

研究过程当中的错误

好了下面上代码~~~~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这些类,还须要再研究研究~~

相关文章
相关标签/搜索