Activiti中如何限制候选组B用户认领usertask1后不可认领usertask2
嘿,这个需求我之前帮人解决过类似的,核心就是要把「认领了usertask1的B组用户」标记出来,然后在usertask2的候选池里把这个人排除掉。给你几个实用的方案,适配不同的实现场景:
方案1:用流程变量+动态候选组表达式(最简单直接)
这个方案不用写太多自定义代码,靠流程引擎的内置表达式就能实现:
- 第一步:在usertask1的任务完成事件里,把认领该任务的用户ID存进子流程的流程变量里,比如叫
task1Assignee。
如果你用Groovy脚本的话,一行就能搞定:
要是用Java执行监听器,代码大概是这样:execution.setVariable("task1Assignee", task.assignee);String assignee = taskService.createTaskQuery().taskId(task.getId()).singleResult().getAssignee(); execution.setVariable("task1Assignee", assignee); - 第二步:给usertask2配置动态候选组,用EL表达式过滤B组用户,把
task1Assignee对应的人排除出去。
假设你的B组标识是groupB,表达式可以这么写:
这样一来,只要是认领了当前子流程usertask1的B组用户,就看不到对应的usertask2了。${groups('groupB').stream().filter(u -> !u.getId().equals(task1Assignee)).collect(Collectors.toList())}
方案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
相关产品推荐
相关产品推荐

