1. 程式人生 > >工作流子流程和多例項開發

工作流子流程和多例項開發

在專案中有子流程和多例項的需求,總結如下:
一、子流程

子流程分為兩種:

  1. CallActivity(呼叫任務)
  2. SubProcess(子流程)

由於呼叫任務能將子任務分離開來,能夠分別顯示單獨的流程圖,實際在專案中用到更多的是呼叫任務,這裡我們主要介紹呼叫任務:
呼叫任務的流程圖如下:
父流程
父流程圖1
子流程
子流程圖2

圖1中我們有一個普通的任務task1和一個呼叫任務,圖2是圖1呼叫任務要呼叫的流程,只有一個普通的任務sonTask,圖中這個任務下面有三道豎線說明它是多例項任務,我們一會兒再介紹,先不管它。
圖中的主要屬性如下:

  • 父流程:{Id:parentProcess};
  • task1:{Id:usertask1,Assignee:parent};
  • 呼叫任務:{Id:callactivity1,Called element:sunProcess}
  • 子流程:{Id:sunProcess};
  • sonTask:{Id:usertask2,Assignee:son};

可以看到呼叫任務的配置很簡單,只需要將Called element的屬性值修改為需要呼叫的子流程id即可。
部署時父子流程都需要部署:

/**
     * 部署流程定義(classpath)
     */
    @Test
    public void deploymentProcessDefinition
() { Deployment dp = pe.getRepositoryService().createDeployment() .name("父子流程") .addClasspathResource("diagrams/Parent.bpmn") .addClasspathResource("diagrams/Parent.png") .addClasspathResource("diagrams/Son.bpmn"
) .addClasspathResource("diagrams/Son.png") .deploy(); System.out.println("部署ID:"+dp.getId()); System.out.println("部署名稱:"+dp.getName()); }

啟動流程例項時只啟動父流程:

/**
     * 啟動流程例項
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "parentProcess";
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey);
        System.out.println("流程例項ID:"+pi.getProcessInstanceId());
        System.out.println("流程定義ID:"+pi.getProcessDefinitionId());
    }

接下來把流程跑通一遍,我們來看一下act_hi_actinst表的資料:
act_hi_actinst表資料

當完成usertask1之後,任務節點到達了callactivity,表中的CALL_PROC_INST_ID_欄位代表了要呼叫哪個流程,這時直接開啟了proc_inst_id_為5003的子流程,完成了startevent1節點,到達了usertask2任務,當完成usertask2之後,子流程結束,父流程結束,整個流程執行完畢。

這是最簡單的呼叫任務,但是如果我們在父流程中設定了流程變數,我們就需要將流程變數傳到子流程當中,這時就需要配置callactivity的Input parameters和Output parameters屬性:
這裡寫圖片描述
其中Source是父流程的流程變數名稱,Target是子流程的流程變數名稱,也就是說子流程和父流程中對應同一個流程變數的名字可以不同,我們對映一下就可以了。同理Output parameters配置的是從子流程中返回的流程變數和父流程的對映關係。如果我們的流程變數是javabean的話,我們就用EL表示式來配置Source expression和Target expression。
我們在父流程中設定一個流程變數name,用來動態的設定子流程usertask2任務的辦理人,我們需要將Source和Target屬性都設定為name,將usertask2的Assignee屬性設定為${name},我們再跑通一次流程,觀察一下表中的變化:
act_ru_variable
act_ru_variable表1
act_hi_actinst
act_hi_actinst表2

我們在啟動父流程的時候設定了流程變數name:


    /**
     * 啟動流程例項
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "parentProcess";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "xiaowang");
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey,map);
        System.out.println("流程例項ID:"+pi.getProcessInstanceId());
        System.out.println("流程定義ID:"+pi.getProcessDefinitionId());
    }

我們看錶一中父流程和子流程都有一個叫name的流程變數,說明流程變數傳進了子流程,同時子流程的usertask2的辦理人設定成了”xiaowang”,完成了動態設定辦理人的需求。outputparameter的設定同理,大家可以自行測試。

這裡還有一個建議,如果有呼叫任務的需求,我們在開發中最好用javabean型別的流程變數來儲存業務資料,否則我們在inputparameter和outputparameter中就需要手動設定所有的流程變數,很麻煩,還需要去程式碼中看我到底設定了哪些流程變數。

二、多例項
單獨的多例項比較簡單,只是配置任務的幾個屬性就可以了。如下:
多例項配置

1.Sequential是設定多例項任務是同步執行還是按照順序執行,”false”為同步執行;
2.Collection是多例項的核心屬性,值為集合型別的流程變數名稱,這裡我在啟動流程例項時設定了一個型別為List的流程變數,名稱為names,程式碼如下:

/**
     * 啟動流程例項
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "sunProcess";
        Map<String, Object> map = new HashMap<String, Object>();
        List<String> names = new ArrayList<String>();
        names.add("xiaowang");
        names.add("xiaoli");
        names.add("xiaozhang");
        map.put("names", names);
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey,map);
        System.out.println("流程例項ID:"+pi.getProcessInstanceId());
        System.out.println("流程定義ID:"+pi.getProcessDefinitionId());
    }

3.Element variable為Collection中每一個元素的名稱,這個名稱是自己定義的,當我們要使用多例項集合中的每一個元素時,總要有個名字。我們在動態設定每一個例項執行物件的Assignee時,用到了這個name:
這裡寫圖片描述
這樣的話,每一個例項就可以根據我們程式中List的每一個元素值來動態設定,我們看一下表中的執行結果:
act_hi_actinst
act_hi_actinst表
這裡我們可以看到同時執行的usertask2有三個,分別動態賦予了不同的Assignee,並且他們的execution_id是不同的,所以在多例項或者有分支和並行的流程中,我們能夠看出流程例項id(proc_inst_id_)和執行物件id(execution_id_)其實是不同的。

不過很多時候多例項流程不只需要動態配置一個assignee屬性,這種時候我們需要將流程變數List中的元素改成javabean物件,在配置assignee時用物件的屬性來配置:
這裡寫圖片描述

這裡需要補充的是所有的多例項跑完才會執行下一步流程。