Activiti 學習(二)—— Activiti 流程定義和部署

概述

在這一節,我們將創建一個 Activit 工作流,並啟動這個流程,主要包含以下幾個步驟:

  1. 定義流程,按照 BPMN 的規範,使用流程定義工具,用流程符號把整個流程描述出來

  2. 部署流程,把畫好的流程定義文件,載入到資料庫中,生成表的數據

流程設計器的使用

在 resources 目錄下創建一個 bpmn 目錄,用來存放流程定義文件。選中 bpmn 目錄,點擊菜單 New -> New Activity 6.x BPMN 2.x file,創建一個 *.bpmn20.xml。選中該文件,右鍵 view BPMN(Activity ) Diagram,可以看到 BPMN-Activiti-Diagram 流程設計頁面。在該頁面右鍵,可以在菜單選擇圖形,拖拽圖形,連線,即可完成流程設計圖

連線的時候,要選中圖形,這時在圖形的右上角會出現一個箭頭符號。雙擊選中箭頭符號,右鍵按住不放即可拉長完成連線

選中一個圖形,下方會出現一個屬性欄,以創建出差申請為例,這裡只填任務名稱和負責人

流程部署

流程部署就是將在設計器中定義的流程部署到 activiti 資料庫中,Activiti 提供了多種部署流程的方式,包括自動部署、classpath 部署、輸入流部署、zip/bar 部署和上傳部署等方式,下面分別進行介紹:

1. 自動部署

Activiti7 可以自動部署流程,前提是在 resources 目錄下,創建一個新的目錄 processes,用來放置 bpmn 文件

2. classpath 部署

classpath 部署方式為採用程式碼進行部署,使用 Java 程式碼實現如下:

public class ActivitDemo {

    @Test
    public void testDeployment() {
        // 1. 創建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2. 獲取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3. 使用 service 進行流程部署,即把 bpmn 部署到資料庫,並定義流程的名稱
        Deployment deploy = repositoryService.createDeployment()
            	// 定義流程資源名稱
                .name("出差申請流程")
            	// 載入待部署的資源,可以多次引用
                .addClasspathResource("bpmn/evection.bpmn20.xml")
            	// 完成部署
                .deploy();
    }
}

3. 輸入流部署

Activiti 提供了按輸入流(InputStream)方式部署資源,輸入流的來源可以有多種,例如本地電腦、classpath 讀取、網路讀取方式等,下面是讀取本地電腦方式進行部署方式的示例程式碼

public class ActivitDemo {

    @Test
    public void testDeployment() {
        // 1. 創建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2. 獲取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3. 獲取輸入流
        String filePath = "D:/workflow/bpmn/evection.bpmn20.xml";
        FileInputStream fileIns = new FileInputStream(filePath);
        // 4. 使用 service 進行流程部署
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申請流程")
                .addInputStream("bpmn/evection.bpmn20.xml", fileIns)
                .deploy();
    }
}

4. zip/bar 部署

將流程資源文件壓縮成 zip 包進行部署,同樣採用流的方式

public void deployProcessByZip() {
    // 1. 獲取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2. 獲取 RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3. 流程部署
    InputStream inputStream = this.getClass()
        .getClassLoader()
        .getResourceAsStream("bpmn/evection.zip");
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    repositoryService.createDeployment()
        .addZipInputStream(zipInputStream)
        .deploy();
}

5. 按字元串方式部署

採用字元串方式進行部署,實際是把一個字元串轉換為位元組流後進行部署,也為開發人員提供了多一種部署方式

public void deployProcessByStr() {
    // 1. 獲取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2. 獲取 RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3. 構建字元串
    String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><definitions>...</definitions>"
    // 4. 流程部署
    repositoryService.createDeployment()
        .name("出差申請流程")
        .addStr("bpmn/evection.bpmn20.xml", str)
        .deploy();
}

採用字元串進行部署的優點是可以通過用戶介面定義一個流程,然後進行部署,或者在測試時,直接將流程程式碼寫入程式,進行流程部署

6. 動態 BPMN 模型部署

通過在程式中動態生成流程模型方式進行部署,動態創建 BPMN,需要在程式中指定每一個元素,並給出元素間的關係,最後將這些元素整合為一個完整的 BPMN

public void testDeploymentByBPMN() {
    // 1. 創建 BPMN 模型實例
    BpmnModel bpmnModel = new BpmnModel();
    // 2. 創建開始事件
    StartEvent startEvent = new StartEvent();
    startEvent.setId("startEvent");
    startEvent.setName("動態創建開始節點");
    // 3. 創建用戶任務
    UserTask userTask = new UserTask();
    userTask.setId("userTask1");
    userTask.setName("用戶任務節點1");
    // 4. 創建結束事件
    EndEvent endEvent = new EndEvent();
    endEvent.setId("endEvent");
    endEvent.setName("動態創建結束節點");
    // 5. 定義連接
    ArrayList<SequenceFlow> sequenceFlows = new ArrayList<>();
    ArrayList<SequenceFlow> toEnd = new ArrayList<>();

    SequenceFlow s1 = new SequenceFlow();
    s1.setId("sequenceFlow1");
    s1.setName("開始節點指向用戶任務節點");
    s1.setSourceRef("startEvent");
    s1.setTargetRef("userTask1");
    sequenceFlows.add(s1);
    SequenceFlow s2 = new SequenceFlow();
    s2.setId("sequenceFlow2");
    s2.setName("用戶任務節點指向結束節點");
    s2.setSourceRef("userTask1");
    s2.setTargetRef("endEvent");
    toEnd.add(s2);

    startEvent.setOutgoingFlows(sequenceFlows);
    userTask.setOutgoingFlows(toEnd);
    userTask.setIncomingFlows(sequenceFlows);
    endEvent.setIncomingFlows(toEnd);

    Process process = new Process();
    process.setId("process1");
    process.setName("test");
    process.addFlowElement(startEvent);
    process.addFlowElement(s1);
    process.addFlowElement(userTask);
    process.addFlowElement(s2);
    process.addFlowElement(endEvent);
    bpmnModel.addProcess(process);
    new BpmnAutoLayout(bpmnModel).execute();
    // 6. 部署
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    Deployment deploy = repositoryService.createDeployment()
        .name("出差申請流程")
        .addBpmnModel("evection.bpmn20.xml", bpmnModel)
        .deploy();
}

7. 相關數據表分析

流程部署後,流程相關的資源全部以數據流的形式存儲到數據表中,實際運行中,流程的處理都是通過調用數據表中的相關資源進行處理,下面介紹流程相關的數據表:

  • act_re_deployment

    流程部署表,用於存放流程定義的部署資訊,部署一個流程就會增加一條記錄

  • act_re_procdef

    流程定義表,用於存放流程定義的屬性資訊,和 act_re_deployment 是一對多的關係,act_re_procdef 表可以有多條記錄,每條記錄對應 act_re_deployment 中的一條記錄

  • act_ge_bytearray

    資源文件表,部署流程時,會將 BPMN 流程定義文件保存為一條記錄,如果部署的流程還包括其他資源,也會增加相應的記錄,例如 png 圖片文件

Tags: