You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Activiti中如何限制候选组B用户认领usertask1后不可认领usertask2

嘿,这个需求我之前帮人解决过类似的,核心就是要把「认领了usertask1的B组用户」标记出来,然后在usertask2的候选池里把这个人排除掉。给你几个实用的方案,适配不同的实现场景:

方案1:用流程变量+动态候选组表达式(最简单直接)

这个方案不用写太多自定义代码,靠流程引擎的内置表达式就能实现:

  • 第一步:在usertask1的任务完成事件里,把认领该任务的用户ID存进子流程的流程变量里,比如叫task1Assignee。
    如果你用Groovy脚本的话,一行就能搞定:
    execution.setVariable("task1Assignee", task.assignee);
    
    要是用Java执行监听器,代码大概是这样:
    String assignee = taskService.createTaskQuery().taskId(task.getId()).singleResult().getAssignee();
    execution.setVariable("task1Assignee", assignee);
    
  • 第二步:给usertask2配置动态候选组,用EL表达式过滤B组用户,把task1Assignee对应的人排除出去。
    假设你的B组标识是groupB,表达式可以这么写:
    ${groups('groupB').stream().filter(u -> !u.getId().equals(task1Assignee)).collect(Collectors.toList())}
    
    这样一来,只要是认领了当前子流程usertask1的B组用户,就看不到对应的usertask2了。
方案2:自定义任务候选人提供者(适合复杂场景)

如果你的业务逻辑后续可能还要扩展,比如加更多排除规则,那自定义一个候选人提供者会更灵活(以Camunda引擎为例):

  • 先写一个实现TaskCandidateSupplier接口的类,里面实现排除逻辑:
    public class ExcludeTask1AssigneeSupplier implements TaskCandidateSupplier {
        @Override
        public List<User> getCandidates(DelegateTask delegateTask) {
            // 获取当前子流程的实例ID
            String subProcessInstanceId = delegateTask.getExecution().getId();
            // 查询这个子流程里usertask1的认领人
            Task task1 = taskService.createTaskQuery()
                .processInstanceId(subProcessInstanceId)
                .taskDefinitionKey("usertask1")
                .singleResult();
            String excludedAssignee = task1 != null ? task1.getAssignee() : null;
            
            // 拿到B组的所有用户
            List<User> groupBUsers = identityService.createUserQuery().memberOfGroup("groupB").list();
            // 排除掉认领了usertask1的用户
            if(excludedAssignee != null) {
                groupBUsers.removeIf(u -> u.getId().equals(excludedAssignee));
            }
            return groupBUsers;
        }
    }
    
  • 把这个类注册成Spring Bean,然后在usertask2的候选组配置里引用它:
    ${excludeTask1AssigneeSupplier.getCandidates(task)}
    
方案3:任务创建监听器动态修改候选组

要是你不想改候选组的配置,也可以在usertask2刚创建的时候,用监听器动态调整它的候选用户:

  • 写一个执行监听器类:
    public class AdjustTask2CandidateListener implements ExecutionListener {
        @Override
        public void notify(DelegateExecution execution) throws Exception {
            // 找到刚创建的usertask2
            Task task2 = taskService.createTaskQuery()
                .executionId(execution.getId())
                .taskDefinitionKey("usertask2")
                .singleResult();
            if(task2 == null) return;
            
            // 查询当前子流程usertask1的认领人
            Task task1 = taskService.createTaskQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .taskDefinitionKey("usertask1")
                .singleResult();
            String excludedAssignee = task1 != null ? task1.getAssignee() : null;
            
            // 获取B组用户并排除目标用户
            List<User> groupBUsers = identityService.createUserQuery().memberOfGroup("groupB").list();
            if(excludedAssignee != null) {
                groupBUsers.removeIf(u -> u.getId().equals(excludedAssignee));
            }
            
            // 给usertask2设置处理后的候选用户
            taskService.addCandidateUsers(task2.getId(), groupBUsers.stream().map(User::getId).collect(Collectors.toList()));
        }
    }
    
  • 把这个监听器绑定到usertask2的创建事件上就行。

注意事项

  • 要确保每个子流程的task1Assignee变量是独立的,别和其他子流程串了(引擎默认的子流程变量隔离机制一般都能满足);
  • 如果你用的是Activiti之类的其他BPMN引擎,API细节可能有点不一样,但核心逻辑都是「记录usertask1的认领人 → 在usertask2的候选者中排除该用户」。

内容的提问来源于stack exchange,提问作者Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:10:49