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

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

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

PS:

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

需求:

  1. 流程中的审批任务节点可以驳回到之前的任意任务节点

  2. 驳回到指定节点的任务之后的轨迹不需要显示

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

思路:

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

115149_tDu1_2849575.gif

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

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

20175406_2go8.png

  1. 启动后查询流程轨迹

20175406_jk6v.png

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

20175406_vl7t.png

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

20175406_uUsV.png

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

20175406_Ee5A.png

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

20175406_uIvJ.png

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

20175407_56ha.png

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

20175407_H5ym.png

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

20175407_cYxb.png

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

20175407_8nPK.png

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

20175407_Ej3o.jpg

好了下面上代码~~~~

代码:

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

转载于:https://my.oschina.net/yzwjyw/blog/1610086

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值