Flowable 中节点任意跳转
工作流开发中经常有一种回退的需求,审批回退、驳回、撤回等都需要。
在 Activiti 中流程底层没开放对应的接口,而在 Flowable 中已经提供了支持节点跳转的功能。同时我们也可以像在 Activiti 中通过实现自己的 Command 来实现任意节点跳转的需求。
下面我们先介绍一下 Flowable 提供的内置跳转功能,最后我们再手动实现任务跳转的 Command。
1. Flowable 内置功能
Flowable 的 RuntimeService 内置了一个强大的功能,可以实现节点到任意节点的跳转。
1 | runtimeService.createChangeActivityStateBuilder() |
上面的代码表示流程实例 ID 为 id
的流程,将 node1
节点的任务跳转到 node2
上。ChangeActivityStateBuilder
类还提供了其它接口可以实现主流程跳子流程,子流程到父流程,非常强大。
运行实例直接跳转到节点
这个接口比较常用,通过取当前运行的实例,我们直接跳转到目标节点,无需关心当前节点是什么。
1 | ChangeActivityStateBuilder moveExecutionToActivityId(String executionId, String activityId); |
跳转到子流程的节点
内嵌子流程直接使用上面的节点跳转方式既可,外部子流程需要启动新的流程,所以接口不太一样。需要提供外部子流程的 CallActivity Id 和在外部子流程中的节点 ID。
1 | ChangeActivityStateBuilder moveActivityIdToSubProcessInstanceActivityId(String currentActivityId, String newActivityId, String callActivityId); |
在跳转的时候还可以修改流程或任务本地变量。
1 | ChangeActivityStateBuilder processVariable(String processVariableName, Object processVariableValue); |
此处我们只说明了几个常用的接口,其它功能可以查看 ChangeActivityStateBuilder
类的源码,注释非常详细。
2. 自制 Command 实现跳转
Flowable 内部也是通过 ChangeActivityStateCmd
这个 Command 实现的,在 Flowable 中其实已经不建议自己实现 Command 来实现了,这里只是提供一种可能性给大家参考。
要自定义 Command 只需要实现 Command
1 | public class JumpCommand implements Command<String> { |
首先我们新建三个变量在存放操作的参数,分别是操作的任务 ID、目标节点的 ID 和注释。
1 | protected String taskId; |
通过任务 ID 取出 Task 内容
1 | ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); |
再通过 Task 对象取出流程,再从流程定义中取出目标节点的流程定义元素
1 | ExecutionEntity executionEntity = executionEntityManager.findById(task.getExecutionId()); |
然后将当前执行实例的节点修改为目标节点,通过 agenda 方式通知 Flowable 通过对象变化补偿完成流程变化
1 | executionEntity.setCurrentFlowElement(targetFlowElement); |
注意,我们通过这种方式将 Task 结束并跳转是不会产生 TASK_COMPLETED
事件的,包括 Flowable 内置的接口,产生的不是 TASK_COMPLETED
而是 ACTIVITY_CANCELLED
事件。
但是这里我们业务预期来说,应该是正常结束任务,产生 TASK_COMPLETED
才对。为了实现这个目标,我们需要手动触发这个事件。
1 | executionEntity.setCurrentFlowElement(targetFlowElement); |
Flowable 中同样需要手动触发
TASK_COMPLETED
事件,因为通过这种方式转的任务触发的是ACTIVITY_CANCELLED
事件。
最后将原来的 Task 删除
1 | task.setExecutionId(null); |
Flowable 中节点任意跳转