跳转到任意节点实现
跳转到任意节点实现
1.在流程运行过程中,任意跳转
需求:如下,执行到节点4的时候,我任务不符合要求,需要驳回/回退到节点1重新开始审批
节点1审批完后也可以重新指向节点4 (跳转到任意节点)
实现思路:
- 将所有的节点设置一个唯一的id,作为跳转的标识
- 首先自己查询出所有执行过的节点,也就是审批节点5之前的节点列表(里面包含每个节点的唯一id/key)
--->可以从自己的业务系统表或者从activiti的历史任务表查 - 选择一个回退的节点,
- 完成当前任务,并设置当前节点的流向为选择的回退节点即可,
注意设置好并执行完回退操作后,记得把当前节点的流向恢复成原来的,不然下次进来的时候会自动扭转到回退节点(因为这里的设置针对的是流程图,而不是流程实例)**
给每个节点设置唯一的id
回退接口实现
/**
*
* @param taskId 当前任务id
* @param nodeId 跳转的节点id
*/
@GetMapping("/backToEveryNode")
@ApiOperation(value = "完成当前任务 并 跳转到任意节点")
public void backToEveryNode(String taskId,String nodeId) {
//当前任务信息
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
//获得当前流程的活动ID
ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
Execution execution = executionQuery.executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
//获取当前节点和目标节点的节点信息
FlowNode currentFlowNode = getFlowNode(task.getProcessDefinitionId(), activityId);
FlowNode targetFlowNode = getFlowNode(task.getProcessDefinitionId(), nodeId);
//获取当前节点的原始流出节点信息
List<SequenceFlow> oldFlowNodeOutgoingFlows = currentFlowNode.getOutgoingFlows();
//重新设置流出节点信息 为退回的节点
SequenceFlow sequenceFlow = new SequenceFlow();
sequenceFlow.setId("newTempSequenceId");
sequenceFlow.setSourceFlowElement(currentFlowNode);
sequenceFlow.setTargetFlowElement(targetFlowNode);//设置流出节点信息 为退回的节点
List<SequenceFlow> newSequenceFlows = new ArrayList<>();
newSequenceFlows.add(sequenceFlow);
currentFlowNode.setOutgoingFlows(newSequenceFlows);
//完成当前任务
taskService.complete(taskId);
//最后恢复原来的流转走向
currentFlowNode.setOutgoingFlows(oldFlowNodeOutgoingFlows);
}
private FlowNode getFlowNode(String processDefinitionId, String activityId) {
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
return (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
}
2.开启实例时 ,指定跳转的节点
实现启动实例时 直接跳到node3
原理同上
- 1.拿到开始节点,保存原始流向
- 2.临时修改流向为指定的节点
- 3.开启实例
- 4.恢复开始节点原来的流向
代码:
/**
* @param procDefId 流程定义id
* @param nodeKey 节点id
*/
@GetMapping("/commitToEveryNode")
@ApiOperation(value = "开启实例 并提交到指定任务节点")
public void commitToEveryNode(String procDefId, String nodeKey) {
//流程定义id
BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);
Process process = bpmnModel.getProcesses().get(0);
//获取所有节点
Collection<FlowElement> flowElements = process.getFlowElements();
System.out.println(flowElements);
//拿到开始节点
if (CollectionUtils.isEmpty(flowElements)) {
throw new RuntimeException("流程图有误,请检查");
}
Collection<FlowElement> startFlowElements = flowElements.stream().filter(bean -> bean instanceof StartEvent).collect(Collectors.toList());
FlowNode startNode = (FlowNode) ((List<FlowElement>) startFlowElements).get(0);
//拿到要跳转的节点
FlowNode jumpNode = getFlowNode(procDefId, nodeKey);
if (jumpNode == null) {
throw new RuntimeException("要跳转的目标节点不存在");
}
//获取当前节点的原始流出节点信息
List<SequenceFlow> oldFlowNodeOutgoingFlows = startNode.getOutgoingFlows();
//临时设置开始节点的流向 为要跳转的节点
SequenceFlow sequenceFlow = new SequenceFlow();
sequenceFlow.setId("newTempSequenceId");
sequenceFlow.setSourceFlowElement(startNode);
sequenceFlow.setTargetFlowElement(jumpNode);
List<SequenceFlow> newSequenceFlows = new ArrayList<>();
newSequenceFlows.add(sequenceFlow);
startNode.setOutgoingFlows(newSequenceFlows);
//开启流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId);
System.out.println(processInstance);
//恢复原来的流转走向
startNode.setOutgoingFlows(oldFlowNodeOutgoingFlows);
}
private FlowNode getFlowNode(String processDefinitionId, String activityId) {
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
return (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
}