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


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

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

    PS:

    从6.0.0降到5.22.0版本的原因因为项目中有一个版本冲突,导致的降级。后期还是以新版本为主。6.0版本的驳回有时间再来搞。

    需求:

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

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

    思路:

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

    点击并拖拽以移动

    根据这个思路,我追了源码,看了各种Service,Manager等等。因为别人的驳回流程我拿下来发现是有错的,所以就自己研究了起来。现在就直接上代码吧。呸。先上图,没图谁会信你成功了呢?

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

    1.启动报销流程

    1. 启动后查询流程轨迹

    2.启动后查询流程轨迹

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

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

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

    4.驳回任务到指定节点

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

    5.驳回后查询

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

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

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

    7启动一个新的流程实例

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

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

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

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

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

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

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

    研究过程中的错误

    好了下面上代码~~~~

    代码:

    每一个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这些类,还需要再研究研究~~

  • 相关阅读:
    R语言 单变量重命名与删除
    R语言 查看函数源代码
    R语言 for循环之break,next
    ROC & AUC笔记
    rmarkdown教程
    github教程
    logistic regression与SVM
    sql语句,order by
    将权重加载到不同的结构(有一些共同层)
    人脸识别数据集
  • 原文地址:https://www.cnblogs.com/tdg-yyx/p/8321399.html
Copyright © 2020-2023  润新知