Camunda技术求助:流程实例创建时批量设置所有UserTask经办人
嗨,我来帮你搞定这个问题!你遇到的核心问题其实是混淆了流程模型定义和流程实例中的任务,还有没搞清楚流程引擎中任务实例的生成时机——下面我给你拆解解决方案:
先搞懂你之前的操作为什么不行
- 你用
execution.getBpmnModelInstance().getModelElementsByType(UserTask.class)拿到的是流程模板里的任务定义,不是当前运行实例中的具体任务。修改这些元素等于改了全局的流程模板,会影响所有新启动的流程,自然没法给当前实例的任务设经办人。 - 用
taskQuery只能查到已经被流程引擎实例化的任务——也就是流程已经走到那个节点、生成了待办的任务。刚启动流程时,只有第一个任务会被实例化,后面的任务还没触发,所以查不到。
解决方案分两种场景
场景1:只处理当前已实例化的任务(流程启动后已生成的待办)
这种情况直接查询当前流程实例下的所有任务实例,然后逐个处理:
// 假设已经启动了流程实例,拿到processInstanceId ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("你的流程Key"); // 查询该实例下所有已创建的用户任务 List<Task> taskInstances = taskService.createTaskQuery() .processInstanceId(processInstance.getId()) .list(); for (Task task : taskInstances) { // 从流程定义中拿到该任务对应的UserTask配置(候选组在这里) BpmnModelInstance bpmnModel = repositoryService.getBpmnModelInstance(processInstance.getProcessDefinitionId()); UserTask userTaskDef = bpmnModel.getModelElementById(task.getTaskDefinitionKey()); // 获取候选组(这里假设每个任务只有一个候选组,根据你的实际情况调整) String candidateGroup = userTaskDef.getCandidateGroups().iterator().next(); // 这里写你的逻辑:根据候选组确定经办人,比如从组里取第一个用户 String assignee = getAssigneeFromGroup(candidateGroup); // 这是你自定义的方法 // 给任务实例设置经办人 taskService.setAssignee(task.getId(), assignee); }
场景2:预分配所有任务的经办人(包括还没走到的任务)
如果希望流程一启动,就把所有节点的经办人都提前确定好,等任务走到时自动赋值,可以用「流程变量存映射+任务创建监听器」的方式:
- 先遍历流程定义中的所有UserTask,根据候选组确定经办人,把映射关系存在流程变量里
- 给每个UserTask配置任务创建监听器,任务生成时自动从流程变量里取经办人赋值
// 启动流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("你的流程Key"); // 获取当前流程的模型定义 BpmnModelInstance bpmnModel = repositoryService.getBpmnModelInstance(processInstance.getProcessDefinitionId()); Collection<UserTask> allUserTaskDefs = bpmnModel.getModelElementsByType(UserTask.class); // 存储「任务Key-经办人」的映射 Map<String, String> taskAssigneeMap = new HashMap<>(); for (UserTask taskDef : allUserTaskDefs) { String taskKey = taskDef.getId(); String candidateGroup = taskDef.getCandidateGroups().iterator().next(); String assignee = getAssigneeFromGroup(candidateGroup); taskAssigneeMap.put(taskKey, assignee); } // 把映射存入流程变量,供后续监听器使用 runtimeService.setVariable(processInstance.getId(), "taskAssigneeMap", taskAssigneeMap);
然后,你需要给每个UserTask添加任务创建监听器——可以在流程建模时直接配置,或者用代码动态添加(如果不能修改模型的话):
// 动态给所有UserTask添加创建监听器(注意:这种方式会修改全局流程定义,如果你不想影响其他实例,建议在建模时配置) for (UserTask taskDef : allUserTaskDefs) { TaskListener createListener = new TaskListener() { @Override public void notify(DelegateTask delegateTask) { // 从流程变量中取出映射 Map<String, String> assigneeMap = (Map<String, String>) delegateTask.getVariable("taskAssigneeMap"); String assignee = assigneeMap.get(delegateTask.getTaskDefinitionKey()); // 设置经办人 delegateTask.setAssignee(assignee); } }; taskDef.addTaskListener(TaskListener.EVENTNAME_CREATE, createListener); } // 更新流程定义(如果是动态添加监听器的话) repositoryService.saveBpmnModelInstance(processInstance.getProcessDefinitionId(), bpmnModel);
小提示
- 如果你的流程有并行网关,流程启动后可能会同时生成多个任务实例,这时候用场景1的方法也能一次性处理所有已生成的任务。
- 确定经办人的逻辑(
getAssigneeFromGroup)要根据你的业务来,比如从用户组里随机选、取组管理员,或者按规则分配,这里只是示例。
内容的提问来源于stack exchange,提问作者Tushar Agarwal
相关产品推荐
相关产品推荐

