Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)

时间:2024-03-31 12:31:47

Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)

原创文章:转载请备注:原创文章地址

需求:

          1.在当前任务节点退回至上一节点;
          2.需要跳过某一个或者几个节点后,指定节点开始继续执行此任务;
          3.在流程运行时跳转到任意一节点(有没有执行过都可以跳转);

这种解决的思路都是同一种方式:

模拟一个需求:nowNode跳转到toNode处

Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)

思路:

1.拿到当前节点(这里称之为nowNode)所有连接其他节点的线(outGoingPath)保存起来,然后删除这些线;

Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)

2.拿到当前节点(nowNode)和指定跳转(toNode)的节点,然后new一条线,连接当前节点(nowNode)和指定节点(toNode);

Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)

3.执行完成任务操作(此时,当前节点因为删除了原本连接着其他节点的线,所有只有刚刚连接着当前节点(nowNode)和指定节点(toNode)的一条线),只有一条线,也就是说任务跳转到指定节点(toNode);
4.恢复原流程图(将new出来的那条线删除,将原本nowNode节点上删除的那些线恢复);

这里就是总体思路,接下来贴代码。

/**
 * 流程转向操作
 *
 * @param taskId     当前任务ID
 * @param activityId 目标节点任务ID
 * @param variables  流程变量
 * @throws Exception
 */
public static void turnTransition(String taskId, String activityId, Map<String, Object> variables) {
    // 当前节点
    ActivityImpl currActivity = findActivitiImpl(taskId, null);
    // 清空当前流向
    List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);

    // 创建新流向
    TransitionImpl newTransition = currActivity.createOutgoingTransition();
    // 目标节点
    ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
    // 设置新流向的目标节点
    newTransition.setDestination(pointActivity);

    // 执行转向任务
    taskService.complete(taskId, variables);
    // 删除目标节点新流入
    pointActivity.getIncomingTransitions().remove(newTransition);

    // 还原以前流向
    restoreTransition(currActivity, oriPvmTransitionList);
}

/**
 * 根据任务ID和节点ID获取活动节点 <br>
 *
 * @param taskId
 * @param activityId 活动节点ID <br>
 *                   如果为null或"",则默认查询当前活动节点 <br>
 *                   如果为"end",则查询结束节点 <br>
 * @return
 * @throws Exception
 */
public static ActivityImpl findActivitiImpl(String taskId, String activityId) {
    // 取得流程定义
    ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(taskService.createTaskQuery().taskId(taskId).singleResult().getProcessDefinitionId());
    // 获取当前活动节点ID
    if (StringUtils.isEmpty(activityId)) {
        activityId = getTaskById(taskId).getTaskDefinitionKey();
    }
    // 根据流程定义,获取该流程实例的结束节点
    ProcessDefinitionImpl processDefinitionImpl = (ProcessDefinitionImpl) getReadOnlyProcessDefinitionByProcDefId(processDefinition.getId());
    if (activityId.toUpperCase().equals("END")) {
        for (ActivityImpl activityImpl : processDefinitionImpl.getActivities()) {
            List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
            if (pvmTransitionList.isEmpty()) {
                return activityImpl;
            }
        }
    }
    // 根据节点ID,获取对应的活动节点
    ActivityImpl activityImpl = processDefinitionImpl.findActivity(activityId);
    // 此处改动,无法获取到对应的活动节点,所以此处采用迂回的方式,如果前面可以取到则跳过,如果没有取到则自己取
    if (activityImpl == null) {
        List<ActivityImpl> activities = processDefinitionImpl.getActivities();
        for (ActivityImpl actImpl : activities) {
            if (actImpl.getId().equals(activityId)) {
                activityImpl = actImpl;
                break;
            }
        }
    }
    return activityImpl;
}
/**
 * 清空指定活动节点现有流向,且将清空的现有流向返回
 *
 * @param activityImpl 活动节点
 * @return 节点流向集合
 */
public static List<PvmTransition> clearTransition(ActivityImpl activityImpl) {
    // 存储当前节点所有流向临时变量
    List<PvmTransition> oriPvmTransitionList = new ArrayList<>();
    // 获取当前节点所有流向,存储到临时变量,然后清空
    List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
    for (PvmTransition pvmTransition : pvmTransitionList) {
        oriPvmTransitionList.add(pvmTransition);
    }
    pvmTransitionList.clear();

    return oriPvmTransitionList;
}
/**
 * 根据任务ID和节点ID获取活动节点 <br>
 *
 * @param taskId
 * @param activityId 活动节点ID <br>
 *                   如果为null或"",则默认查询当前活动节点 <br>
 *                   如果为"end",则查询结束节点 <br>
 * @return
 * @throws Exception
 */
public static ActivityImpl findActivitiImpl(String taskId, String activityId) {
    // 取得流程定义
    ProcessDefinitionEntity processDefinition = getProcDefEntityByTaskId(taskId);
    // 获取当前活动节点ID
    if (StringUtils.isEmpty(activityId)) {
        activityId = getTaskById(taskId).getTaskDefinitionKey();
    }
    // 根据流程定义,获取该流程实例的结束节点
    ProcessDefinitionImpl processDefinitionImpl = (ProcessDefinitionImpl) getReadOnlyProcessDefinitionByProcDefId(processDefinition.getId());
    if (activityId.toUpperCase().equals("END")) {
        for (ActivityImpl activityImpl : processDefinitionImpl.getActivities()) {
            List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
            if (pvmTransitionList.isEmpty()) {
                return activityImpl;
            }
        }
    }
    // 根据节点ID,获取对应的活动节点
    ActivityImpl activityImpl = processDefinitionImpl.findActivity(activityId);
    // 此处改动,无法获取到对应的活动节点,所以此处采用迂回的方式,如果前面可以取到则跳过,如果没有取到则自己取
    if (activityImpl == null) {
        List<ActivityImpl> activities = processDefinitionImpl.getActivities();
        for (ActivityImpl actImpl : activities) {
            if (actImpl.getId().equals(activityId)) {
                activityImpl = actImpl;
                break;
            }
        }
    }
    return activityImpl;
}
/**
 * 清空指定节点现有流向,且将新流向接入
 *
 * @param activityImpl         活动节点
 * @param oriPvmTransitionList 新流向节点集合
 */
public static void restoreTransition(ActivityImpl activityImpl, List<PvmTransition> oriPvmTransitionList) {
    // 清空现有流向
    List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
    pvmTransitionList.clear();
    // 还原以前流向
    for (PvmTransition pvmTransition : oriPvmTransitionList) {
        pvmTransitionList.add(pvmTransition);
    }
}


ps:简版不涉及1.单任务回退并行节点(单变多);

        2.并行任务节点回退单任务节点(多变单);

        3.并行任务节点回退并行任务节点(多变多);

        4.并行多实例回退并行多实例任务(恶心);

    这些会留在以后的文章讲解。