Activiti6.0(十)任務處理人變更(改派)、自由跳轉(回退)

目錄

一、前言

二、改派實現

三、自由跳轉實現

思路1

思路2


一、前言

流程流轉時,某個環節的任務處理人變更(即改派)是一種非常常見的需求,本來任務處理人可能是A,但是A因爲有事處理不了,管理員需要將該單子改派給B臨時處理下。

在中國式流程中,流程的 回退 也是必不可少的,流程流轉到某個環節時,處理人一看:咦 這填的都是啥玩意兒,根本不符合要求,想直接打回給上一環節或者走過的任意環節,那麼就需要支持回退功能;有時候流程方面還有特殊的需求,比如越級上報,某些處理人權限比較高運行跳過某些環節直接執行,甚至說可以一步走到底,這便依賴Activiti的自由流程

本文就簡單介紹下Activiti中如何實現改派和回退。

 

二、改派實現

在實際使用Activiti中,絕大多數公司都是有一套自己的用戶管理系統,而且Activiti自身的用戶和用戶組功能其實也並不能滿足部分需求,比如想分配給一個部門、一個角色等等。因此Activiti中的人員信息其實不是那麼重要,在我們項目中甚至不會從裏面去獲取人員信息,僅僅只是設值。Activiti的任務處理人主要是存放在 ACT_RU_TASK 的 ASSIGNEE_ 字段中以及ACT_RU_IDENTITYLINK,前者主要是單個審覈人的情況,後者主要是候選人的情況。

其實改派的實現很簡單,就是爲當前任務重新設置處理人,調用如下方法即可:

taskService.setAssignee("taskId", "userId");

當使用流程變量的方式設置處理人時,在業務上可能是多個處理人或處理組,因此在 ASSIGNEE_ 中存的可能是個用戶數組,形如:[a,b,b] 。由於 ASSIGNEE_ 字段是varchar類型且僅爲255,因此用戶id如果是uuid格式的話,最多隻能存儲7個...

設置處理人的api還挺多,還有一種方式也行:

taskService.unclaim("taskId");
taskService.claim("taskId", "userId");

該方式與上面的主要區別是,claim方法會去檢查當前是否已經有處理人,如果有則會拋錯,需要先調用 unclaim 方法。

 

三、自由跳轉實現

Activiti6的最大變化便是對代碼的重構,其去掉了原先的pvm,直接針對bpmn處理,因此性能上會有些許提升(也沒試驗過,之前項目中使用的是Activiti5.22,因此原先的自由跳轉與6的實現已經完全不一樣了,題外話,pvm主要就是負責流程整個運行期的執行、流轉等所有運行操作,其所有實現類都在org.activiti.engine.impl.pvm包裏,但是6全部移除了...)

這裏主要演示回退的場景,先看上面的流程圖,假設當前任務已經流轉到領導審批,領導一看,你這審批信息填的不正確鴨,需要駁回,啪一點,此時流程需回退到審批信息填寫環節,如何實現呢?

思路1

在運行過程中,動態修改Activiti的流程定義,修改領導審批環節的出線,使之流轉到審批信息填寫,在流轉完成後再恢領導審批原先的出線(即結束環節),該方式雖然也能實現自由跳轉,但是存在併發的問題,假設A點擊回退,此時流程定義已經被修改,領導審批的出線已經變爲審批信息填寫,同時B點擊提交,卻發現流程流轉到了審批信息填寫...B說簡直見了鬼。因此不可取

思路2

使用執行計劃直接指定當前流程實例執行所選環節,由於在併發情況下當前任務的執行id是唯一的,因此該方式也沒有帶來不安全性,下面基於此實現貼代碼:

首先是兩個命令,即刪除當前任務命令以及執行自由跳轉命令:

/**
 * 繼承NeedsActiveTaskCmd主要是爲了在跳轉時要求當前任務不能是掛起狀態,也可以直接實現Command接口
 * Created by xujia on 2020/2/10
 */
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);
        // 返回當前任務的執行對象id
        return executionEntity.getId();
    }
    public String getSuspendedTaskException() {
        return "掛起的任務不能跳轉";
    }
}

/**
 * 執行自由跳轉命令
 * Created by xujia on 2020/2/10
 */
public class SetFLowNodeAndGoCmd implements Command<Void> {

    /**
     * 目標節點對象
     */
    private FlowNode flowElement;
    /**
     * 當前任務執行id
     */
    private String executionId;

    public SetFLowNodeAndGoCmd(FlowNode flowElement,String executionId){
        this.flowElement = flowElement;
        this.executionId = executionId;
    }

    public Void execute(CommandContext commandContext){
        // 獲取目標節點的來源連線
        List<SequenceFlow> flows = flowElement.getIncomingFlows();
        if(flows==null || flows.size()<1){
            throw new ActivitiException("回退錯誤,目標節點沒有來源連線");
        }
        // 隨便選一條目標節點的入線來執行,使當前執行計劃爲:從所選擇的流程線流轉到目標節點,實現跳轉
        ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findById(executionId);
        executionEntity.setCurrentFlowElement(flows.get(0));
        commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true);
        return null;
    }
}

然後是調用:

@Test
    public void listTaskTest() {
        // 獲取當前任務
        Task currentTask = taskService.createTaskQuery().taskId("132502").singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());
        // 獲取流程定義
        Process process = bpmnModel.getMainProcess();
        // 獲取目標節點定義
        FlowNode targetNode = (FlowNode) process.getFlowElement("sid-C24BA4F5-F744-4DD7-8D51-03C3698044D2");

        // 刪除當前運行任務,同時返回執行id,該id在併發情況下也是唯一的
        String executionEntityId = managementService.executeCommand(new DeleteTaskCmd(currentTask.getId()));
        // 流程執行到來源節點
        managementService.executeCommand(new SetFLowNodeAndGoCmd(targetNode, executionEntityId));
    }

運行之後就會發現流程直接流轉到審批信息填寫環節,且處理人也變成原先的處理人,靈活運用可實現多種多樣的需求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章