1. 程式人生 > >springBoot整合Activiti5.0

springBoot整合Activiti5.0

一、工作流簡介

1.什麼是工作流?

簡單的理解就是工作的流程,這裡的流程指的是,完成一個企業中具體業務的一系列工作步驟,所有的步驟合在一起就是業務從開始到結束的流轉過程。

從計算機系統的角度來講,工作流系統表示:業務過程的部分和整體在計算機應用環境的自動化操作。

 

2.工作流的三大要素

①這個過程要做什麼?

②經過多少個步驟?

③每個步驟是由誰來做,做什麼,怎麼做?

 

3.工作流系統的組成

流程定義工具:定義流程(畫流程圖)

表單定製工具:要提交的資料的表單的定製(可以用建立一個(html form)表單的表單形式替代)

工作流引擎: 工作流框架的核心,驅動著流程的流程,流程的資料共享,資料儲存,流程的版本迭代....

管理監控工具:監控每一個流程的運轉,管理每一個流程;

開發API:暴露給開發人員的api;

 

 

4.工作流需要解決的問題

    1)、流程的自動化流程控制

    2)、流程資料的儲存(歷史記錄,歷史資料的儲存);

    3)、流程版本的更替;(維護流程的版本更替);

    4)、流程執行期間資料的共享等;

流程都具有一定的通用性;流程框架抽取流程的通用性,來統一管理和維護流程;

 

5.工作流的相關概念

①流程定義:(ProcessDefinition):

    流程的定義:流程圖。表示一個流程的資訊;一個流程定義(如:請假流程圖)

②流程例項:(ProcessInstance):

    啟動一個流程:稱為建立一個流程的例項;無數個流程例項(如員工提交的請假單審批流程)

③流程變數:(ProcessVariable):

    流程執行提交的資料,共享的資料,等;

④任務:(Task)

    每一步需要完成的工作算是一個任務;(每一個流程執行都需要完成自己的流程規定的任務)

⑤開始、結束(Start 、End)

    每一個流程只有一個入口,無數的出口;(正常結束的出口,異常結束的出口等)

⑥閘道器(Gateway):

    流程的分支節點(判斷節點);決定下一步走哪兒;

 

6.工作流產品

①JBPM

②OSWorkFlow

③Shark

④信雅達

⑤普元工作流

⑥Activiti5

 

 

7.ProcessEngine

ProcessEngine這個類是Activiti5的核心,所有的服務都需要通過ProcessEngine來建立,該類是執行緒安全的

Activiti5的持久化層採用的是Mybatis,這樣移植性好,底層Spring+MyBatis;

Activiti5主要包括7個Service,這些Service都是通過ProcessEngine建立 

repositoryService(持久化服務)

runtimeService(執行時服務)

formService(表單服務)

identityService(身份資訊)

taskService(任務服務)

historyService(歷史資訊)

managementService(管理定時任務)

 

 

8.Activiti5框架表結構

Activiti使用到的表都是ACT_開頭的。

ACT_RE_*: ‘RE’表示repository(儲存),RepositoryService介面所操作的表。帶此字首的表包含的是靜態資訊,如,流程定義,流程的資源(圖片,規則等)。

ACT_RU_*: ‘RU’表示runtime,執行時表-RuntimeService。這是執行時的表儲存著流程變數,使用者任務,變數,職責(job)等執行時的資料。Activiti只儲存例項執行期間的執行時資料,當流程例項結束時,將刪除這些記錄。這就保證了這些執行時的表小且快。

ACT_ID_*: ’ID’表示identity (組織機構),IdentityService介面所操作的表。使用者記錄,流程中使用到的使用者和組。這些表包含標識的資訊,如使用者,使用者組,等等。

ACT_HI_*: ’HI’表示history,歷史資料表,HistoryService。就是這些表包含著流程執行的歷史相關資料,如結束的流程例項,變數,任務,等等

ACT_GE_*: 全域性通用資料及設定(general),各種情況都使用的資料。

 

act_ge_bytearray二進位制資料表

act_ge_property屬性資料表儲存整個流程引擎級別的資料,初始化表結構時,會預設插入三條記錄,

act_hi_actinst歷史節點表

act_hi_attachment歷史附件表

act_hi_comment歷史意見表

act_hi_identitylink歷史流程人員表

act_hi_detail歷史詳情表,提供歷史變數的查詢

act_hi_procinst歷史流程例項表

act_hi_taskinst歷史任務例項表

act_hi_varinst歷史變量表

act_id_group使用者組資訊表

act_id_info使用者擴充套件資訊表

act_id_membership使用者與使用者組對應資訊表

act_id_user使用者資訊表

act_re_deployment部署資訊表

act_re_model流程設計模型部署表

act_re_procdef流程定義資料表

act_ru_event_subscr  throwEvent、catchEvent時間監聽資訊表

act_ru_execution執行時流程執行例項表

act_ru_identitylink執行時流程人員表,主要儲存任務節點與參與者的相關資訊

act_ru_job執行時定時任務資料表

act_ru_task執行時任務節點表

act_ru_variable執行時流程變數資料表

 

9.流程框架的標準

Business Process Management (BPM). 工作流管理系統

BPMN 2.0:Business Process Modeling Notation(中文:業務流程建模與標註)

 

OMG組織維護業務流程建模規範,以後所有流程框架繪製流程圖都遵循這個規範;

 

二、流程框架的操作

1)、設計流程:畫流程圖;

 

2)、儲存流程:給資料庫中儲存繪製的流程圖(流程定義)

3)、匯出流程:實際上繪製的流程是一個xml檔案;bmpn規範;


<?xml version="1.0" encoding="UTF-8"?>

<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">

  <process id="電話費報銷" name="話費報銷" isExecutable="true">

    <startEvent id="startevent1" name="Start"></startEvent>

    <userTask id="usertask1" name="部門經理審批"></userTask>

    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>

    <userTask id="usertask2" name="財務審批"></userTask>

    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>

    <userTask id="usertask3" name="總經理審批"></userTask>

    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>

    <endEvent id="endevent1" name="End"></endEvent>

    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>

  </process>

  <bpmndi:BPMNDiagram id="BPMNDiagram_電話費報銷">

    <bpmndi:BPMNPlane bpmnElement="電話費報銷" id="BPMNPlane_電話費報銷">

      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">

        <omgdc:Bounds height="35.0" width="35.0" x="90.0" y="190.0"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">

        <omgdc:Bounds height="55.0" width="105.0" x="170.0" y="180.0"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">

        <omgdc:Bounds height="55.0" width="105.0" x="320.0" y="180.0"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">

        <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="180.0"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">

        <omgdc:Bounds height="35.0" width="35.0" x="640.0" y="190.0"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">

        <omgdi:waypoint x="125.0" y="207.0"></omgdi:waypoint>

        <omgdi:waypoint x="170.0" y="207.0"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">

        <omgdi:waypoint x="275.0" y="207.0"></omgdi:waypoint>

        <omgdi:waypoint x="320.0" y="207.0"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">

        <omgdi:waypoint x="425.0" y="207.0"></omgdi:waypoint>

        <omgdi:waypoint x="470.0" y="207.0"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">

        <omgdi:waypoint x="575.0" y="207.0"></omgdi:waypoint>

        <omgdi:waypoint x="640.0" y="207.0"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

    </bpmndi:BPMNPlane>

  </bpmndi:BPMNDiagram>

</definitions>


<process></process>規定整個流程的流轉;

<userTask ></userTask>規定使用者任務;

<sequenceFlow></sequenceFlow>指定流轉方向等...

 

4)、流程部署:實際就是把流程的定義資訊(詳情)儲存到資料庫; 給資料儲存了流程定義

5)、啟動流程:按照流程定義啟動一次流程(流程例項)

6)、流程例項:流程框架控制自動流轉到下一步;

7)、簽收任務完成任務;完成以後,流程框架自動判斷來到下一步

8)、檢視歷史流程    

 

三、Activiti5框架的幾大元件

 

ProcessEngine :流程框架的核心 ;獲取各大元件

activiti的七大元件:都是由流程引擎得到的;

以下為元件的獲取方式:


ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

 

RuntimeService runtimeService = processEngine.getRuntimeService();

RepositoryService repositoryService = processEngine.getRepositoryService();

TaskService taskService = processEngine.getTaskService();

ManagementService managementService = processEngine.getManagementService();

IdentityService identityService = processEngine.getIdentityService();

HistoryService historyService = processEngine.getHistoryService();

FormService formService = processEngine.getFormService();


 

四、Activiti5的使用

1.導包(Activiti5預設使用的是h2的記憶體資料庫,如果要使用mysql需要匯入響應的驅動包)


        <dependency>

            <groupId>org.activiti</groupId>

            <artifactId>activiti-engine</artifactId>

            <version>5.22.0</version>

        </dependency>

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

            <version>5.1.42</version>

        </dependency>


 

2.編寫流程框架配置檔案(檔名:activiti.cfg.xml)


<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- id必須是這個名稱 -->

    <bean id="processEngineConfiguration"

        class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <!--資料庫的連線相關資訊 -->

        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti" />

        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />

        <property name="jdbcUsername" value="root" />

        <property name="jdbcPassword" value="123456" />

        <!-- 第一次啟動創鍵資料庫;以後升級資料庫表結構 -->

        <property name="databaseSchemaUpdate" value="true" />

        <property name="jobExecutorActivate" value="false" />

        <property name="asyncExecutorEnabled" value="true" />

        <property name="asyncExecutorActivate" value="false" />

        

        <!--設定解決亂碼問題  -->

        <property name="activityFontName" value="微軟雅黑"></property>

        <property name="annotationFontName" value="微軟雅黑"></property>

        <property name="labelFontName" value="微軟雅黑"></property>

    </bean>

</beans>


 

3.獲取流程引擎


    public static void main(String[] args) {

        //第一次獲取流程引擎會建立很多表

        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

        System.out.println(engine.toString());

    }


第一次建立資料表時,此表中會有三條記錄:

 

 



五、在eclipse中使用activiti5繪製流程圖

1.安裝繪製流程圖的外掛

 

 

2.部署流程(把流程定義(流程圖)儲存到資料庫中);每次部署產生一個【流程定義】


    /**

     * 部署專案

     */

    @Test

    public void testDeployement() {

        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = engine.getRepositoryService();

        Deployment deployment = repositoryService.createDeployment().addClasspathResource("話費報銷流程.bpmn").deploy();

        System.out.println(deployment.getName());

        System.out.println(deployment.getId());

        System.out.println(deployment.getDeploymentTime());

    }


資料庫效果:

act_ge_bytearray

 act_re_deployment

 act_re_procdef

 id_:流程定義的唯一id;流程引擎自動生成的;

rev_:資料庫樂觀鎖機制

category_:分類

name_:流程定義的名字

key_:流程定義的key

version_:流程的版本號

deployment_id:那次部署產生的這個流程定義

resource_name_:流程定義的xml檔案的名字;

dgrm_resource_name_:流程圖的檔案的名字;

其他等等的資訊...

 

每一個流程圖都有三個資料;

 同一個流程部署多次會產生多個版本;根據每一個流程圖的id來區分;


 

 

3.查詢流程部署資訊


    /**

     * 檢視資料庫的流程部署資訊

     */

    @Test

    public void testQueryPdeployment() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();

        List<Deployment> list = deploymentQuery.list();

        

        for (Deployment deployment : list) {

            

            System.out.println("部署流程id"+deployment.getId());

            System.out.println("部署流程名字"+deployment.getName());

            System.out.println("部署流程時間"+deployment.getDeploymentTime());

        }

    }


4.查詢流程定義資訊


    /**

     * 檢視資料庫的流程定義資訊

     */

    @Test

    public void testQueryPdefintion(){

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        

        //獲取資料庫中所有的流程定義資訊

        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

        for (ProcessDefinition processDefinition : list) {

            System.out.println("部署的定義目錄"+processDefinition.getCategory());

            System.out.println("部署的定義id"+processDefinition.getDeploymentId());

            System.out.println("部署的定義key"+processDefinition.getKey());

            System.out.println("部署的定義name"+processDefinition.getName());

            System.out.println("部署的定義版本"+processDefinition.getVersion());

            System.out.println("部署的定義流程圖資源名"+processDefinition.getDiagramResourceName());

        }

        

        

    }


 

3.啟動流程


    /**

     * 啟動一個流程

     */

    @Test

    public void testStart() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

        ProcessDefinition processDefinition = processDefinitionQuery.processDefinitionVersion(2).singleResult();

        

        RuntimeService runtimeService = processEngine.getRuntimeService();

        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());

        System.out.println("流程啟動完成"+processInstance);

        

    }


4.查詢任務,簽收任務


   如果某個任務已經固定分配給某個人了,就不能再簽了;如果要籤,先要撤銷簽收unclaim; 

    /**

     * 查詢當前流程執行的任務;

     */

    @Test

    public void testQueryTask() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        TaskService taskService = processEngine.getTaskService();

        //查詢當前任務

        Task task = taskService.createTaskQuery().singleResult();

        System.out.println(task);

        //簽收任務

        taskService.claim(task.getId(), "admin");

        System.out.println("admin簽收了"+task);

        

    }


5.執行任務,並自動流轉到下一個流程


    /**

     * 執行任務

     */

    @Test

    public void testQueryTaskByUser() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        TaskService taskService = processEngine.getTaskService();

        //獲取admin要執行的任務

        Task task = taskService.createTaskQuery().taskAssignee("admin").singleResult();

        //執行任務

        taskService.complete(task.getId());

        System.out.println("admin完成任務"+task);

    }


6.查詢任務的執行歷史


    /**

     * 查詢任務的執行歷史

     */

    @Test

    public void testHistory() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //獲取HistoryService進行歷史任務的檢索等操作

        HistoryService historyService = processEngine.getHistoryService();

        //查詢所有已經完成的流程例項

        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processFinished().list();

        for (HistoricTaskInstance historicTaskInstance : list) {

            //查詢那個歷史任務是由誰在什麼時間開始,在什麼時間結束

            System.out.println(historicTaskInstance);

            System.out.println(historicTaskInstance.getName()+"===>"+historicTaskInstance.getAssignee()+"===>"+historicTaskInstance.getStartTime()+"===>"+historicTaskInstance.getEndTime());

        }

    }