activiti&flowable任意驳回-获取可驳回节点信息

本文详细介绍了在Flowable 6.6.0版本中处理工作流退回操作的复杂场景,包括串行路线、并行网关等不同情况。通过查询运行节点表获取可驳回节点信息,并提供了获取审批人的方法。文章提供了具体的代码实现,展示了如何构造和排序可驳回节点列表,为后续的驳回操作提供了基础。

 我们经常需要工作流中退回上一步,或者退回历史某一个节点。但由于流程的场景是很复杂的,回退有以下一些场景:

1.串行路线上的退回:流程中没有任何网关(排他网关/并行网关)和会签多实例。

2.退回到并行网关分支中的某一个节点上。

3.并行网关中的某一个分支节点上发起退回,退回到并行网关前面的某一个节点上。

4.子流程中退回到主干流程中某一个节点/主干流程退回到子流程中某一个节点。
 

flowable版本:6.6.0

我们都知道驳回的api:

runtimeService.createChangeActivityStateBuilder().processInstanceId(proInstanceId)
     .moveActivityIdTo(currentActivityId, newActivityId).changeState();
或者
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(        
     currentExecutionIds, newActivityId).changeState();

但是其实不好处理的是如何获取可驳回节点信息,task任务是没有驳回需要的activityId的,言归正传,下面提供下我的实现方案:

/**
     * 获取可驳回节点,排序规则-最近的节点在前面
     *
     * @param taskId            任务id
     * @param processInstanceId 流程实例id
     * @return
     */
public List<FlowNodeDto> getCanRejectedFlowNode(String taskId, String processInstanceId) {
        List<FlowNodeDto> backNodes = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String currActId = task.getTaskDefinitionKey();
        //获取运行节点表中usertask
        String sql = "select t.* from ACT_RU_ACTINST t where t.ACT_TYPE_ = 'userTask' " +
                " and t.PROC_INST_ID_=#{processInstanceId} and t.END_TIME_ is not null ";
        List<ActivityInstance> activityInstances = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", processInstanceId)
                .list();
        //获取运行节点表的parallelGateway节点并出重
        sql = "SELECT t.ID_, t.REV_,t.PROC_DEF_ID_,t.PROC_INST_ID_,t.EXECUTION_ID_,t2.ACT_ID_, t.TASK_ID_, t.CALL_PROC_INST_ID_, t.ACT_NAME_, t.ACT_TYPE_, " +
                " t.ASSIGNEE_, t.START_TIME_, t2.END_TIME_, t.DURATION_, t.DELETE_REASON_, t.TENANT_ID_" +
                " FROM  ACT_RU_ACTINST t JOIN (SELECT
### Flowable 排驳回功能实现 在处理复杂的工作流场景时,排驳回(即不允许重复驳回到同一节点)是一个常见的需求。为了满足这一需求,在Flowable框架内可以通过自定义行为和服务任务来实现。 #### 自定义服务任务以控制流向逻辑 一种方法是创建一个特定的服务任务,在该任务中编写Java代码来判断当前实例是否已经访问过目标活动,并阻止再次进入相同的活动[^1]: ```java public class ExclusiveRejectionServiceTask extends JavaDelegate { @Override public void execute(DelegateExecution execution) { String targetActivityId = (String)execution.getVariable("targetActivity"); List<HistoricActivityInstance> historyInstances = historyService.createHistoricActivityInstanceQuery() .processInstanceId(execution.getProcessInstanceId()) .activityId(targetActivityId) .list(); if (!historyInstances.isEmpty()) { throw new BpmnError("REJECTION_DENIED", "Cannot reject back to an already visited activity."); } // 继续执行其他必要的操作... } } ``` 此段代码会在每次尝试返回到之前已到达过的节点时触发异常并终止流程进展,从而实现了排驳回的效果。 #### 使用监听器拦截事件 另一种方式则是利用Flowable提供的`ExecutionListener`接口,在特定时刻捕获流程中的变化情况。可以在要保护的任务前设置监听器,当检测到来自不期望的方向的转换请求时,则采取措施中断或重定向流程路径[^2]: ```xml <userTask id="taskA" name="Task A"> <extensionElements> <activiti:executionListener event="start" class="com.example.ExclusiveRejectionExecutionListener"/> </extensionElements> </userTask> <!-- ... --> <bpmn:startEvent id="theStart"></bpmn:startEvent> <bpmn:endEvent id="theEnd"></bpmn:endEvent> ``` 对应的Java类如下所示: ```java public class ExclusiveRejectionExecutionListener implements ExecutionListener { private static final long serialVersionUID = 1L; @Autowired HistoryService historyService; @Override public void notify(DelegateExecution execution) throws Exception { Object sourceTransition = execution.getVariableLocal("sourceTransition"); if ("unwantedSource".equals(sourceTransition)) { // 如果是从不应该来的方向过来, 则做相应处理. System.out.println("Blocked unwanted transition!"); // 这里可以选择抛出错误或者其他形式的通知机制. } else { // 正常情况下继续向下走. System.out.println("Allowed normal transition."); } } } ``` 这两种方案都可以有效防止流程被不当逆转至先前已完成的状态,具体选择取决于项目的架构和个人偏好。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值