Activiti任务退回、任意跳转(任务调度)功能实现及思路(简版)
原创文章:转载请备注:原创文章地址
需求:
1.在当前任务节点退回至上一节点;
2.需要跳过某一个或者几个节点后,指定节点开始继续执行此任务;
3.在流程运行时跳转到任意一节点(有没有执行过都可以跳转);
这种解决的思路都是同一种方式:
模拟一个需求:nowNode跳转到toNode处
思路:
1.拿到当前节点(这里称之为nowNode)所有连接其他节点的线(outGoingPath)保存起来,然后删除这些线;
2.拿到当前节点(nowNode)和指定跳转(toNode)的节点,然后new一条线,连接当前节点(nowNode)和指定节点(toNode);
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.并行多实例回退并行多实例任务(恶心);