activiti6.0源碼剖析之多實(shí)例減簽與加簽操作

一、什么是多實(shí)例減簽,多實(shí)例加簽

比如配置了一個(gè)多實(shí)例用戶實(shí)例闷堡,由三人串行或者并行執(zhí)行,那么現(xiàn)在的需求是某個(gè)個(gè)例不需要那么多人了疑故,只需要兩個(gè)人也就是減少一個(gè)人杠览,這樣的操作稱為減簽操作。

反之纵势,當(dāng)需要添加一個(gè)人員參與會(huì)簽時(shí)的操作踱阿,就稱之為加簽操作。

二吨悍、多實(shí)例減簽(僅支持6版本)

思路

通過(guò)多實(shí)例運(yùn)轉(zhuǎn)過(guò)程很容易能夠理清如何實(shí)現(xiàn)減簽操作,如果需要明白運(yùn)轉(zhuǎn)過(guò)程可以參考activiti6.0源碼剖析之多實(shí)例運(yùn)轉(zhuǎn)過(guò)程

以該流程圖為例說(shuō)明


并行流程.png

減簽可以從兩種角度去看:被減掉的是以已經(jīng)執(zhí)行成功來(lái)做蹋嵌,還是壓根就當(dāng)作沒(méi)有存在過(guò)
根據(jù)上述兩種角度可以大致理清以下思路

  • 首先根據(jù)需要減掉的任務(wù)Id獲取到該任務(wù)ID所屬的三級(jí)執(zhí)行實(shí)例

  • 然后根據(jù)三級(jí)執(zhí)行實(shí)例ID或者多多實(shí)例執(zhí)行實(shí)例的父級(jí)實(shí)例(二級(jí)實(shí)例)

  • 通過(guò)二級(jí)執(zhí)行實(shí)例刪除需要減掉的三級(jí)執(zhí)行實(shí)例數(shù)據(jù)育瓜,任務(wù)數(shù)據(jù)

  • 根據(jù)二級(jí)執(zhí)行實(shí)例獲取nrOfInstances,nrOfCompletedInstances,nrOfActiveInstances,loopCounter變量栽烂,并根據(jù)并行或者串行多實(shí)例躏仇,根據(jù)上述兩種角度進(jìn)行相應(yīng)的變更

    • 如果是串行多實(shí)例減簽
      正常執(zhí)行完成的角度上:nrOfCompletedInstances 1,nrOfActiveInstances保持1不變腺办,loopCounter 1
      非正常完成的角度上:nrOfInstances 1焰手,loopCounter 1

    • 如果是并行多實(shí)例減簽
      正常執(zhí)行完成的角度上:nrOfCompletedInstances 1,nrOfActiveInstances 1怀喉,
      非正常完成的角度上:nrOfInstances 1书妻,nrOfActiveInstances 1,

實(shí)戰(zhàn)


public class DeleteMultiInstanceCmd implements Command {
    protected final String NUMBER_OF_INSTANCES = "nrOfInstances";
    protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
    protected final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
    protected String collectionElementIndexVariable = "loopCounter";

    private String taskId;
    private Boolean isNormalComplete;

    public DeleteMultiInstanceCmd(String taskId,boolean isNormalComplete) {
        this.taskId = taskId;
        this.isNormalComplete = isNormalComplete;
    }

    public Object execute(CommandContext commandContext) {
           ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();

        //根據(jù)任務(wù)id獲取任務(wù)實(shí)例
        TaskEntity taskEntity = taskEntityManager.findById(taskId);
        //根據(jù)執(zhí)行實(shí)例ID獲取三級(jí)執(zhí)行實(shí)例
        ExecutionEntity execution = executionEntityManager.findById(taskEntity.getExecutionId());
        //首先判斷當(dāng)前任務(wù)是否是屬于多實(shí)例節(jié)點(diǎn)
        String processDefinitionId = execution.getProcessDefinitionId();
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);
        Activity activityElement = (Activity)bpmnModel.getFlowElement(execution.getCurrentActivityId());
        MultiInstanceLoopCharacteristics loopCharacteristics = activityElement.getLoopCharacteristics();
        if(loopCharacteristics == null){
            throw new RuntimeException("沒(méi)有找到多實(shí)例");
        }
        if(!(activityElement.getBehavior() instanceof MultiInstanceActivityBehavior)){
            throw new RuntimeException("此節(jié)點(diǎn)不是多實(shí)例節(jié)點(diǎn)");
        }
        DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration().getDeploymentManager();
        ProcessDefinition definition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
        //判斷是否是5的版本
        if(Activiti5Util.isActiviti5ProcessDefinition(commandContext,definition)){
            throw new RuntimeException("不支持5版本");
        }

        boolean isSequential = loopCharacteristics.isSequential();
        //獲取二級(jí)執(zhí)行實(shí)例
        ExecutionEntity sencondExecution = execution.getParent();
        //刪除所要?jiǎng)h除的實(shí)例相關(guān)數(shù)據(jù)
        if(!isSequential){
            //并行多實(shí)例
            executionEntityManager.deleteChildExecutions(execution,"減簽",false);
            executionEntityManager.deleteExecutionAndRelatedData(execution,"減簽",true);
        }

        //獲取二級(jí)執(zhí)行實(shí)例關(guān)聯(lián)的變量
        Integer nrOfInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_INSTANCES);
        Integer nrOfActiveInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_ACTIVE_INSTANCES);
        Integer nrOfCompletedInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_COMPLETED_INSTANCES);
        //更新二級(jí)執(zhí)行實(shí)例關(guān)聯(lián)的變量
        if(isNormalComplete){
            //正常完成
            sencondExecution.setVariable(NUMBER_OF_COMPLETED_INSTANCES,nrOfCompletedInstances+1 );
            if(isSequential){
                //串行多實(shí)例
                Integer loopCounter =getLoopVariable(execution,collectionElementIndexVariable);
                execution.setVariableLocal(collectionElementIndexVariable,loopCounter+1);
            }else{
                //并行多實(shí)例
                sencondExecution.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances-1);
            }
        }else{
            //非正常(就當(dāng)作沒(méi)有過(guò)此任務(wù))
            sencondExecution.setVariableLocal(NUMBER_OF_INSTANCES,nrOfInstances-1);
            if(isSequential){
                //串行多實(shí)例
                Integer loopCounter = (Integer) execution.getVariable(collectionElementIndexVariable);
                execution.setVariableLocal(collectionElementIndexVariable,loopCounter+1);
            }else{
                //并行多實(shí)例
                //并行多實(shí)例
                sencondExecution.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances-1);
            }
        }
        //刪除任務(wù)
        taskEntityManager.delete(taskId);

        //觸發(fā)流程運(yùn)轉(zhuǎn)
        ActivitiEngineAgenda agenda = commandContext.getAgenda();
        agenda.planContinueProcessInCompensation(execution);


        return null;
    }
    protected Integer getLoopVariable(DelegateExecution execution, String variableName) {
        Object value = execution.getVariableLocal(variableName);
        DelegateExecution parent = execution.getParent();
        while (value == null && parent != null) {
            value = parent.getVariableLocal(variableName);
            parent = parent.getParent();
        }
        return (Integer) (value != null ? value : 0);
    }
}


三躬拢、并行多實(shí)例加簽

思路

  • 根據(jù)業(yè)務(wù)需求獲取到多實(shí)例父級(jí)執(zhí)行實(shí)例
  • 判斷當(dāng)前節(jié)點(diǎn)是否是并行多實(shí)例
  • 根據(jù)多實(shí)例父級(jí)實(shí)例創(chuàng)建多實(shí)例執(zhí)行實(shí)例(也就是新加的人員所在執(zhí)行實(shí)例)
  • 為新建的多實(shí)例執(zhí)行實(shí)例設(shè)置當(dāng)前處理節(jié)點(diǎn)
  • 更改多實(shí)例父級(jí)執(zhí)行實(shí)例的變量

    nrOfInstances+1
    nrOfActiveInstances+1

  • 通知該活動(dòng)開(kāi)始
  • 獲取行為類
  • 執(zhí)行行為類

實(shí)戰(zhàn)

public class AddMultiInstanceCmd implements Command {
    protected final String NUMBER_OF_INSTANCES = "nrOfInstances";
    protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
    private String multiRootExecutionId;
    private String addUserTaskAssign;

    public AddMultiInstanceCmd(String multiRootExecutionId, String addUserTaskAssign) {
        this.multiRootExecutionId = multiRootExecutionId;
        this.addUserTaskAssign = addUserTaskAssign;
    }


    public Object execute(CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        //獲取多實(shí)例父級(jí)執(zhí)行實(shí)例
        ExecutionEntity multiExecutionEntity = executionEntityManager.findById(multiRootExecutionId);
        //判斷當(dāng)前執(zhí)行實(shí)例的節(jié)點(diǎn)是否是多實(shí)例節(jié)點(diǎn)
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(multiExecutionEntity.getProcessDefinitionId());
        Activity miActivityElement = (Activity) bpmnModel.getFlowElement(multiExecutionEntity.getCurrentActivityId());
        MultiInstanceLoopCharacteristics loopCharacteristics = miActivityElement.getLoopCharacteristics();
        if(loopCharacteristics == null){
            throw new ActivitiException("此節(jié)點(diǎn)不是多實(shí)例節(jié)點(diǎn)");
        }
        //判斷是否是并行多實(shí)例
        if(loopCharacteristics.isSequential()){
            throw new ActivitiException("此節(jié)點(diǎn)為串行節(jié)點(diǎn)");

        }
        //創(chuàng)建新的子實(shí)例
        ExecutionEntity childExecution = executionEntityManager.createChildExecution(multiExecutionEntity);
        //獲取并為新的執(zhí)行實(shí)例設(shè)置當(dāng)前活動(dòng)節(jié)點(diǎn)
        UserTask currentFlowElement = (UserTask) multiExecutionEntity.getCurrentFlowElement();
        //設(shè)置處理人
        currentFlowElement.setAssignee(addUserTaskAssign);
        childExecution.setCurrentFlowElement(currentFlowElement);

        //獲取設(shè)置變量
        Integer nrOfInstances = (Integer) multiExecutionEntity.getVariableLocal(NUMBER_OF_INSTANCES);
        Integer nrOfActiveInstances = (Integer) multiExecutionEntity.getVariableLocal(NUMBER_OF_ACTIVE_INSTANCES);

        multiExecutionEntity.setVariableLocal(NUMBER_OF_INSTANCES,nrOfInstances+1);
        multiExecutionEntity.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances+1);

        //通知活動(dòng)開(kāi)始
        HistoryManager historyManager = commandContext.getHistoryManager();
        historyManager.recordActivityStart(childExecution);
        //獲取處理行為類
        ParallelMultiInstanceBehavior prallelMultiInstanceBehavior = (ParallelMultiInstanceBehavior) miActivityElement.getBehavior();
        AbstractBpmnActivityBehavior innerActivityBehavior = prallelMultiInstanceBehavior.getInnerActivityBehavior();
        //執(zhí)行
        innerActivityBehavior.execute(childExecution);
        return null;
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末躲履,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子聊闯,更是在濱河造成了極大的恐慌工猜,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菱蔬,死亡現(xiàn)場(chǎng)離奇詭異篷帅,居然都是意外死亡史侣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門魏身,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惊橱,“玉大人,你說(shuō)我怎么就攤上這事叠骑±罨剩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵宙枷,是天一觀的道長(zhǎng)掉房。 經(jīng)常有香客問(wèn)我,道長(zhǎng)慰丛,這世上最難降的妖魔是什么卓囚? 我笑而不...
    開(kāi)封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮诅病,結(jié)果婚禮上哪亿,老公的妹妹穿的比我還像新娘。我一直安慰自己贤笆,他們只是感情好蝇棉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著芥永,像睡著了一般篡殷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上埋涧,一...
    開(kāi)封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天板辽,我揣著相機(jī)與錄音,去河邊找鬼棘催。 笑死劲弦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的醇坝。 我是一名探鬼主播邑跪,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呼猪!你這毒婦竟也來(lái)了呀袱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郑叠,失蹤者是張志新(化名)和其女友劉穎夜赵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乡革,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寇僧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年摊腋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘁傀。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兴蒸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出细办,到底是詐尸還是另有隱情橙凳,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布笑撞,位于F島的核電站岛啸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏茴肥。R本人自食惡果不足惜坚踩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓤狐。 院中可真熱鬧瞬铸,春花似錦、人聲如沸础锐。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)皆警。三九已至拦宣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耀怜,已是汗流浹背恢着。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工桐愉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留财破,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓从诲,卻偏偏與公主長(zhǎng)得像左痢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子系洛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 如果想直接看結(jié)果則直接翻到最后看總結(jié) Start俊性、多實(shí)例運(yùn)轉(zhuǎn)過(guò)程分析 多實(shí)例運(yùn)轉(zhuǎn)過(guò)程中的要素(變量):在所有多執(zhí)行...
    我有一只喵喵閱讀 4,755評(píng)論 2 4
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,103評(píng)論 1 32
  • iOS多線程編程 基本知識(shí) 1. 進(jìn)程(process) 進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,就是一段程序的執(zhí)...
    陵無(wú)山閱讀 6,055評(píng)論 1 14
  • 垃圾收集基礎(chǔ) Java 語(yǔ)言的一大特點(diǎn)就是可以進(jìn)行自動(dòng)垃圾回收處理描扯,而無(wú)需開(kāi)發(fā)人員過(guò)于關(guān)注系統(tǒng)資源定页,例如內(nèi)存資源的...
    Austin_Brant閱讀 746評(píng)論 0 2
  • 隨著開(kāi)發(fā)組成員越來(lái)越多推送代碼的頻率也越來(lái)越高,也就避免不了出現(xiàn)合錯(cuò)分支而且推送到了遠(yuǎn)程branch上绽诚。之前遇到多...
    zZ天涯閱讀 6,437評(píng)論 0 0