Activiti实现跳转(驳回)的方式

1,700 阅读2分钟

1.流程图配置连线,正常流转

最为安全可靠,不修改Activiti自身执行和流程定义对象,但是对于中国式流程的功能需求(驳回、回退等),经常是要求在没有连线的情况下完成跳转,灵活性不够。

2.动态修改流程定义环节的连线,然后执行跳转,完成后再恢复流程定义

这种方法可以实现动态跳转,不需要修改Activiti自身执行,但是会动态修改系统中的流程定义缓存对象。理论上这会出现一个多线程下,全局变量不安全的问题。单个Activiti流程引擎中,流程定义缓存对象是被所有线程共用的,当一个应用服务器同时收到两个不同流程实例、同个流程定义、同个环节的任务提交请求。a要求驳回,所以该线程动态修改了流程定义;与此同时,b要求正常流转,但是执行过程中,依据的流程定义已被修改,可能导致b也走向了驳回。

Activiti5中实现,文中第二种

Activiti6中实现

3.直接指定当前流程实例执行所选的环节

Activiti5中实现

Activiti5中实现,文中第一种

//跳转方法
public void jump(String taskId){
        //当前任务
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        //获取流程定义
        Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess();
        //获取目标节点定义
        FlowNode targetNode = (FlowNode)process.getFlowElement("startTask");
        //删除当前运行任务
        String executionEntityId = managementService.executeCommand(new DeleteTaskCmd(currentTask.getId()));
        //流程执行到来源节点
        managementService.executeCommand(new SetFLowNodeAndGoCmd(targetNode, executionEntityId));
    }
------------------
//删除当前运行时任务命令,并返回当前任务的执行对象id
//这里继承了NeedsActiveTaskCmd,主要时很多跳转业务场景下,要求不能时挂起任务。可以直接继承Command即可
public class DeleteTaskCmd extends NeedsActiveTaskCmd<String> {
    public DeleteTaskCmd(String taskId){
        super(taskId);
    }
    public String execute(CommandContext commandContext, TaskEntity currentTask){
        //获取所需服务
        TaskEntityManagerImpl taskEntityManager = (TaskEntityManagerImpl)commandContext.getTaskEntityManager();
        //获取当前任务的来源任务及来源节点信息
        ExecutionEntity executionEntity = currentTask.getExecution();
        //删除当前任务,来源任务
        taskEntityManager.deleteTask(currentTask, "jumpReason", false, false);
        return executionEntity.getId();
    }
    public String getSuspendedTaskException() {
        return "挂起的任务不能跳转";
    }
}
------------------
//根据提供节点和执行对象id,进行跳转命令
public class SetFLowNodeAndGoCmd implements Command<Void> {
    private FlowNode flowElement;
    private String executionId;
    public SetFLowNodeAndGoCmd(FlowNode flowElement,String executionId){
        this.flowElement = flowElement;
        this.executionId = executionId;
    }

    public Void execute(CommandContext commandContext){
        //获取目标节点的来源连线
        List<Sequence