在Activiti工作流引擎中,用户任务(UserTask)是一种常见的任务类型,它允许用户在流程中执行特定的操作,为了满足不同的业务需求,我们可能需要为用户任务分配多个角色,本文将介绍如何扩展activiti-userTask以支持分配多个角色,并提供详细的技术介绍。
一、什么是activiti-userTask?
activiti-userTask是Activiti工作流引擎中的一个组件,用于表示用户自定义的任务,用户任务允许用户在流程中执行特定的操作,例如审批、通知等,在activiti-userTask中,我们可以通过配置表单和任务描述来定义任务的输入和输出。
二、为什么要扩展activiti-userTask以支持分配多个角色?
在某些场景下,我们可能需要为用户任务分配多个角色,一个审批流程中可能包含多个审批人,我们需要让这些审批人都能完成审批任务,为了实现这个需求,我们需要扩展activiti-userTask以支持分配多个角色。
三、如何扩展activiti-userTask以支持分配多个角色?
1. 创建一个新的Java类,继承自`org.activiti.engine.impl.bpmn.usertask.UserTaskImpl`,并重写`createExecutionListener`方法,在这个方法中,我们可以修改原有的执行监听器,使其能够处理多个角色的分配。
import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.TaskListener; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.delegate.ExecutionListener; import org.activiti.engine.impl.pvm.runtime.Operation; import org.activiti.engine.impl.pvm.runtime.ProcessInstance; import org.activiti.engine.impl.task.TaskBase; import org.activiti.engine.impl.util.CommandContextUtil; import org.activiti.engine.task.DelegationState; import org.springframework.stereotype.Component; @Component public class MultiRoleUserTask extends TaskBase { @Override public void createExecutionListener(DelegateTask delegateTask) { // 调用父类的createExecutionListener方法,获取原有的执行监听器 super.createExecutionListener(delegateTask); } }
2. 在新的Java类中,添加一个方法`assignMultipleRoles`,用于为用户任务分配多个角色,在这个方法中,我们首先获取用户任务的实例,然后遍历所有的角色,为每个角色创建一个执行监听器,并将这些监听器添加到用户任务的执行监听器列表中。
public void assignMultipleRoles(String taskId, List<String> roleIds) { UserTask userTask = CommandContextUtil.getProcessEngineConfiguration().getDeploymentCache() .findUserTaskDefinitionById(taskId); if (userTask == null) { throw new IllegalArgumentException("Invalid task id: " + taskId); } ExecutionEntity executionEntity = userTask.getExecution(); if (executionEntity == null) { throw new IllegalStateException("Invalid execution entity for task: " + taskId); } DelegateTask delegateTask = (DelegateTask) executionEntity; for (String roleId : roleIds) { String listenerClassName = "com.example.MultiRoleUserTask$" + roleId + "ExecutionListener"; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try { Class<?> listenerClass = classLoader.loadClass(listenerClassName); ExecutionListener listener = (ExecutionListener) listenerClass.newInstance(); delegateTask.addListener(listener); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { throw new RuntimeException("Failed to create execution listener for role: " + roleId, e); } catch (NoSuchMethodException | InvocationTargetException e) { throw new RuntimeException("Failed to invoke constructor for listener class: " + listenerClassName, e); } finally { classLoader = null; // release the classloader reference after loading the class and creating the instance of the listener class } } }
3. 在新的Java类中,添加一个方法`executeWithMultipleRoles`,用于模拟具有多个角色的用户任务的执行过程,在这个方法中,我们首先获取用户任务的实例,然后调用`assignMultipleRoles`方法为用户任务分配多个角色,接下来,我们创建一个新的流程实例,并启动该流程实例,我们等待流程实例结束。
public void executeWithMultipleRoles(String taskId, List<String> roleIds) throws Exception { UserTask userTask = CommandContextUtil.getProcessEngineConfiguration().getDeploymentCache() .findUserTaskDefinitionById(taskId); if (userTask == null) { throw new IllegalArgumentException("Invalid task id: " + taskId); } ExecutionEntity executionEntity = userTask.getExecution(); if (executionEntity == null) { throw new IllegalStateException("Invalid execution entity for task: " + taskId); } DelegateTask delegateTask = (DelegateTask) executionEntity; assignMultipleRoles(taskId, roleIds); // 为用户任务分配多个角色 Object variableValue = delegateTask.getVariable("assignee"); // 获取当前任务的执行者变量值(这里假设只有一个角色被分配给用户任务) assertEquals("user1", variableValue); // 确保当前任务的执行者是user1(这里假设只有一个角色被分配给用户任务) ExecutionStartContext startContext = new ExecutionStartContext(); // 创建流程实例启动上下文对象(注意:这里没有传递任何参数给流程定义) ExecutionEntity processInstance = startContext // 通过流程定义ID启动流程实例(注意:这里没有传递任何参数给流程定义) .setCurrentFlowElement((FlowNode) delegateTask) // 将当前任务设置为流程节点(注意:这里没有传递任何参数给流程定义) .start(); // 启动流程实例(注意:这里没有传递任何参数给流程定义) assertTrue("Process instance was not created", processInstance != null); // 确保流程实例已经被创建(注意:这里没有传递任何参数给流程定义) assertTrue("Process instance does not have an activity execution", processInstance.getCurrentActivityId() != null); // 确保流程实例已经开始执行(注意:这里没有传递任何参数给流程定义) }
4. 在新的Java类中,实现`ExecutionListener`接口,用于处理具有多个角色的用户任务的执行过程,在这个类中,我们可以根据当前执行者的角色来调整我们的逻辑,如果当前执行者的角色是user1,我们可以执行一些特定的操作;如果当前执行者的角色是user2,我们可以执行另外一些操作,以下是一个简单的示例: