Activiti使用


Activiti是一個開源的工作流引擎,它實現了BPMN 2.0規范,可以發布設計好的流程定義,並通過api進行流程調度。

Activiti 作為一個遵從 Apache 許可的工作流和業務流程管理開源平台,其核心是基於 Java 的超快速、超穩定的 BPMN2.0 流程引擎,強調流程服務的可嵌入性和可擴展性,同時更加強調面向業務人員。

Activiti 流程引擎重點關注在系統開發的易用性和輕量性上。每一項 BPM 業務功能 Activiti 流程引擎都以服務的形式提供給開發人員。通過使用這些服務,開發人員能夠構建出功能豐富、輕便且高效的 BPM 應用程序。

核心組件介紹

1. 關鍵對象

  1. Deployment:流程部署對象,部署一個流程時創建。
  2. ProcessDefinitions:流程定義,部署成功后自動創建。
  3. ProcessInstances:流程實例,啟動流程時創建。
  4. Task:任務,在Activiti中的Task僅指有角色參與的任務,即定義中的UserTask。
  5. Execution:執行計划,流程實例和流程執行中的所有節點都是Execution,如UserTask、ServiceTask等。

2. 服務接口

  1. ProcessEngine:流程引擎的抽象,通過它我們可以獲得我們需要的一切服務。
  2. RepositoryService:Activiti中每一個不同版本的業務流程的定義都需要使用一些定義文件,部署文件和支持數據(例如BPMN2.0 XML文件,表單定義文件,流程定義圖像文件等),這些文件都存儲在Activiti內建的Repository中。RepositoryService提供了對 repository的存取服務。
  3. RuntimeService:在Activiti中,每當一個流程定義被啟動一次之后,都會生成一個相應的流程對象實例。RuntimeService提供了啟動流程、查詢流程實例、設置獲取流程實例變量等功能。此外它還提供了對流程部署,流程定義和流程實例的存取服務。
  4. TaskService: 在Activiti中業務流程定義中的每一個執行節點被稱為一個Task,對流程中的數據存取,狀態變更等操作均需要在Task中完成。TaskService提供了對用戶Task 和Form相關的操作。它提供了運行時任務查詢、領取、完成、刪除以及變量設置等功能。
  5. IdentityService: Activiti中內置了用戶以及組管理的功能,必須使用這些用戶和組的信息才能獲取到相應的Task。IdentityService提供了對Activiti 系統中的用戶和組的管理功能。
  6. ManagementService: ManagementService提供了對Activiti流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程序中使用,主要用於Activiti系統的日常維護。
  7. HistoryService: HistoryService用於獲取正在運行或已經完成的流程實例的信息,與RuntimeService中獲取的流程信息不同,歷史信息包含已經持久化存儲的永久信息,並已經被針對查詢優化。

現在至少要知道有這些對象和接口。並結合Activiti Api這一章節來看,你就會對部署流程、啟動流程、執行任務等操作有一個基本的概念。之后編寫一個簡單的單元測試,主要為了測試activiti.cfg.xml配置的是否正確,流程是否可以被部署即可。

至於與Spring的集成,一定要熟悉基於Spring配置Activiti,以及事務的處理。

官方demo使用(activiti-explorer)

activiti工作流歷史版本下載,更改版本號后在瀏覽器地址欄回車即可

https://github.com/Activiti/Activiti/releases/download/activiti-5.16.3/activiti-5.16.3.zip

下載后解壓得到:

 

初始化數據庫(本文采用的mysql數據庫)

\wars\activiti-explorer.war解壓到tomcat的webapps下,並修改\activiti-explorer\WEB-INF\classes中的db.properties:

#db=h2
#jdbc.driver=org.h2.Driver
#jdbc.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
#jdbc.username=sa
#jdbc.password=

db=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1/activititest?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

訪問首頁,打開瀏覽器輸入http://localhost:8080/activiti-explore,使用用戶kermit,密碼kermit登錄

 

 

 

 

使用idea進行activiti工作流開發

1.安裝IDEA中編輯Activiti流程的插件actiBPM,安裝完成后重啟IDEA

2.新建一個maven工程,pom.xml文件內容為:

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xuan</groupId>
    <artifactId>testactiviti</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>testactiviti</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <!--<scope>test</scope>-->
        </dependency>
        <!--- Activiti依賴導入 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>5.22.0</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>5.22.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>spring-beans</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>jackson-core-asl</artifactId>
                    <groupId>org.codehaus.jackson</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-lang3</artifactId>
                    <groupId>org.apache.commons</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-lang3</artifactId>
                    <groupId>org.apache.commons</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--MySQL 驅動包,如果是其他庫的話需要換驅動包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
    </dependencies>
</project>

創建資源文件夾resource,並把目錄設置為Test Resources Root

目錄結構為

 

在resource目錄中新建activiti.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl"
                  value="jdbc:mysql://localhost:3306/testactiviti?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"></property>
        <property name="jdbcUsername" value="root"></property>
        <property name="jdbcPassword" value="123456"></property>
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>
</beans>

在resources下面新建一個WorkTest.bpmn文件:

 

新建之后頁面會變成如下圖所示這樣,中間是畫布,右邊是一些元素,左邊是每個元素的一些詳細信息,直接拖拽右邊的元素就可以畫流程了。

畫完流程圖之后可以更改整個流程的name和元素的name,assignee,

但是畫圖之后,沒有連接圖標怎么辦呢
把鼠標放在開頭的那個圖標上,此時光標的形狀改變了。 拖到另一個上面,連接成功了。
怎么連接成功的呢? 把鼠標放到圖標的正中心,然后會看到光標變成了“扇子類型”的樣子(黑白相間)。只要看到變成這個樣子,就可以拖動到另一個圖標中,進行連接了

我這里畫的一個很簡單的流程圖,只用到了startEvent、endEvent和userTask。我的流程是做的訂單的審批。如圖:

畫完圖后,但是並沒有生成png圖片,這個時候重命名剛才創建的文件,把后綴改成xml,然后右鍵

 

這個時候發現顯示的時候有亂碼:

 

解決方法:

找到idea安裝目錄bin目錄下如下圖所示兩個文件,用編輯器打開,在文件末尾添加 -Dfile.encoding=UTF-8 ,然后重啟idea,再打開流程圖就會發現中文已經可以正常顯示了。

 

 解決問題后,把xml文件重新改成bpmn格式,和png圖片一起壓縮成zip包進行部署。

1.創建需要的表格

Activiti提供使用代碼或者配置文件的方式來配置數據庫的信息,新建MyActiviti.java來生成數據庫信息:

public class MyActiviti {
    @Test
    public void creatTable() {
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine();
        System.out.println("processEngine:"+ processEngine);
    }

    @Test
    public void creatTable2() {
        ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        //連接數據庫配置
        processEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
        processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8");
        processEngineConfiguration.setJdbcUsername("root");
        processEngineConfiguration.setJdbcPassword("123456");

        /**
         public static final String DB_SCHEMA_UPDATE_FALSE = "false";//不能自動創建表,需要表存在
         public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";//先刪除表再創建表
         public static final String DB_SCHEMA_UPDATE_TRUE = "true";//如果表不存在,自動創建表
         */
        processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP);
        //工作流的核心對象,ProcessEngine對象
        ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
        System.out.println("processEngine:"+ processEngine);
    }
}

運行這個類的creatTable或creatTable2之后,自動幫我們把對應的數據庫表創建起來,有些說23-25張表都是有可能的,我這里是生成了25張表。

所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。 用途也和服務的API對應。

  • ACT_RE_*: 'RE'表示repository。 這個前綴的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。
  • ACT_RU_*: 'RU'表示runtime。 這些運行時的表,包含流程實例,任務,變量,異步任務,等運行中的數據。 Activiti只在流程實例執行過程中保存這些數據, 在流程結束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。
  • ACT_ID_*: 'ID'表示identity。 這些表包含身份信息,比如用戶,組等等。
  • ACT_HI_*: 'HI'表示history。 這些表包含歷史數據,比如歷史流程實例, 變量,任務等等。
  • ACT_GE_*: 通用數據, 用於不同場景下,如存放資源文件。

每個表和字段的具體含義可以參考:https://blog.csdn.net/hj7jay/article/details/51302829

2.部署流程

建表成功之后就可以開始部署流程了,部署之后就可以在act_re_procdef表中看到對相應的流程信息.

    @Test
    public void deploy() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        DeploymentBuilder builder = repositoryService.createDeployment();//創建一個部署的構建器
        builder.addClasspathResource("WorkTest.bpmn");//從類路徑中添加資源,一次只能添加一個資源
        builder.name("訂單審批");
        builder.category("辦公類別");
        Deployment deploy = builder.deploy();

        System.out.println("部署的id" + deploy.getId());
        System.out.println("部署的名稱" + deploy.getName());
    }
    //查詢流程
    @Test
    public void queryProcdef() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //創建查詢對象
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        //添加查詢條件
        //query.processDefinitionKey("myProcess_2");//通過key獲取
        // .processDefinitionName("My process")//通過name獲取
        query.orderByProcessDefinitionId().asc();//根據ID排序
        //執行查詢獲取流程定義明細
        List<ProcessDefinition> pds = query.list();
        for (ProcessDefinition pd : pds) {
            System.out.println("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName());
        }
    }

 

3.執行工作流

    @Test
    public void startProcess() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //指定執行我們剛才部署的工作流程,就是bomn文件定義的流程ID或者名稱
        String processDefiKey = "myProcess_1";
        //取運行時服務
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //取得流程實例
        ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通過流程定義的key 來執行流程
        System.out.println("流程實例id:" + pi.getId());//流程實例id
        System.out.println("流程定義id:" + pi.getProcessDefinitionId());//輸出流程定義的id
    }

啟動流程之后就會有相應的任務產生,存在act_ru_task表中,可以查看任務節點

4.查詢信息

    @Test
    public void queryTask() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        //processInstanceId,就是act_ru_task的PROC_INST_ID_
        String processInstanceId = "12501";
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();

        //首次運行的時候這個沒有輸出,因為第一次運行的時候掃描act_ru_task的表里面是空的,但第一次運行完成之后里面會添加一條記錄,之后每次運行里面都會添加一條記錄
        for (Task task : tasks) {
            System.out.println("taskId:" + task.getId() +
                    ",taskName:" + task.getName() +
                    ",assignee:" + task.getAssignee() +
                    ",createTime:" + task.getCreateTime());
        }
    }

也可以根據其它各種條件進行查詢

    //查詢流程定義明細
    @Test
    public void queryProcdef() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //創建查詢對象
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        //添加查詢條件
        query.processDefinitionKey("myProcess_1");//通過key獲取
        // .processDefinitionName("My process")//通過name獲取
        // .orderByProcessDefinitionId()//根據ID排序
        //執行查詢獲取流程定義明細
        List<ProcessDefinition> pds = query.list();
        for (ProcessDefinition pd : pds) {
            System.out.println("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName());
        }
    }

5.處理任務

    //完成任務
    @Test
    public void compileTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        String taskId="12504";//任務id,act_ru_task的ID_
        processEngine.getTaskService().complete(taskId);
        System.out.println("當前任務執行完畢");
    }

其它還有刪除流程等各種操作,可以參考https://segmentfault.com/a/1190000013839729


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM