Activity工作流(2)-入門安裝運行第一個例子

1. 初識Activiti

1.1. 工作流與工作流引擎

工作流(workflow)就是工作流程的計算模型,即將工作流程中的工作如何前後組織在一起的邏輯和規則在計算機中以恰當的模型進行表示並對其實施計算。它主要解決的是“使在多個參與者之間按照某種預定義的規則傳遞文檔、信息或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現”。(我的理解就是:將部分或者全部的工作流程、邏輯讓計算機幫你來處理,實現自動化)

所謂工作流引擎是指workflow作爲應用系統的一部分,併爲之提供對各應用系統有決定作用的根據角色、分工和條件的不同決定信息傳遞路由、內容等級等核心解決方案。

例如開發一個系統最關鍵的部分不是系統的界面,也不是和數據庫之間的信息交換,而是如何根據業務邏輯開發出符合實際需要的程序邏輯並確保其穩定性、易維護性和彈性。

比如你的系統中有一個任務流程,一般情況下這個任務的代碼邏輯、流程你都要自己來編寫。實現它是沒有問題的。但是誰能保證邏輯編寫的毫無紕漏?經過無數次的測試與改進,這個流程沒有任何漏洞也是可以實現的,但是明顯就會拖慢整個項目的進度。

工作流引擎解決的就是這個問題:如果應用程序缺乏強大的邏輯層,勢必變得容易出錯(信息的路由錯誤、死循環等等)。

1.2. BPMN2.0規範

BPMN(Business Process Model and Notation)–業務流程模型與符號。

BPMN是一套流程建模的標準,主要目標是被所有業務用戶容易理解的符號,支持從創建流程輪廓的業務分析到這些流程的最終實現,知道最終用戶的管理監控。

通俗一點其實就是一套規範,畫流程模型的規範。流程模型包括:流程圖、協作圖、編排圖、會話圖。詳細信息請google。
1.3. Activiti概述
1.3.1. Activiti由來

學習過Activiti的朋友都知道,Activiti的創始人也就是JBPM(也是一個優秀的BPM引擎)的創始人,從Jboss離職後開發了一個新的BPM引擎:Activiti。所以,Activiti有很多地方都有JBPM的影子。所以,據說學習過JBPM的朋友學起Activiti來非常順手。

由於本人之前沒有工作流及JBPM的相關基礎,剛開始學習Activiti的時候可以說是無比痛苦的,根本不知道從何下手,這裏也建議大家先進行工作流及BPMN2.0規範的學習,有了一定的基礎後,再着手學習Activiti。
1.3.2. Activiti簡介

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

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

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

以上部分對工作流、BPMN、Activiti的概念做了一個簡單的介紹,目的是瞭解Activiti究竟是什麼,能做些什麼…及在學習Activiti之前需要了解的知識與技術。其中大部分文字來自Copy網上的各種資料與文檔,通過總結而來的。具體的更詳細的內容需自己google,參考一些官方的文檔與手冊。

本文檔之後內容如下:

1) 下載與使用

2) 核心組件與說明

3) 入門示例

4) Eclipse中的Activiti插件的使用

本文檔旨在爲初學Activiti的朋友提供入門級別的參考,不會對其原理及其結構進行深層次的探究(更多是因爲目前自身理解還不是很透徹),只是爲大家理清思路,方便以後更深層次的學習。本文檔還有一個重要的特點,那就是根據自己看官方手冊的經驗,教大家如何看手冊從而更有效率!由於是初學,很多術語或解釋難免理解有偏差,所以一定要看官方提供的文檔與手冊,那纔是學習的最佳途徑!

2. 開始學習

2.1. 必要的準備
2.1.1. 下載與瞭解目錄

下載Activiti:下載路徑,也就是官方網站的地址:http://activiti.org/download.html。下載後解壓(我所使用的是5.12版本的,Activiti更新速度飛快,幾乎每兩個月就會有一個更新的小版本),看到如下目錄:

1) database:裏面存放的是Activiti使用到的數據庫信息的sql文件,它支持的數據庫類型如下圖,使用時只需執行你自己的數據庫類型的文件即可。如:你的數據庫是MySQL,那麼就執行activiti.mysql.create.*.sql即可。

2) docs:毫無疑問,api文檔是也。

3) libs:使用Activiti所需要的所有的jar包和源文件。

4) wars:官方給我們提供的示例Demo,通過使用Demo可以更加快速的瞭解Activiti。
2.1.2. 其他準備

使用Activiti,首先當然要有jdk了!6+版本就可以了。其次,要有一款IDE,我們當然會使用Eclipse,這裏使用Juno版本。然後,web容器當然也要有,這裏使用Tomcat6.0版本。然後就是Activiti的Eclipse插件了,這個後面再介紹。
2.1.3. 一分鐘入門(見用戶手冊)

所謂的一分鐘入門就是通過運行你下載的包裏的wars文件夾裏的activiti-explorer.war文件,以便更快的瞭解Activiti。將文件拷貝至Tomcat的webapps目錄,啓動tomcat,輸入http://localhost:8080/activiti-explorer。然後你就可以開整了!總算是有一點微小的進展了。

這裏需要說明的就是,這個Demo默認採用的是h2內存數據庫,如果想用你自己的數據庫,就需要修改web應用WEB-INF/classes目錄下的db.properties。然後,按上面說的,把database裏的create文件夾裏的數據庫文件導入你自己的數據庫(如果沒有修改db.properties,就不用導入了)。

Demo的具體解釋與數據庫配置的具體信息詳見官方手冊,手冊已經說的很清楚了。這裏需要重點了解activiti.cfg.xml的配置以及如何構建ProcessEngine(配置文件構建方式、代碼構建方式)。

對Demo的使用介紹在官方文檔的後面纔開始介紹,這裏建議應用跑起來之後,先自己試試手(可看後面介紹Demo如何使用的章節),看看如何跑一個流程、整個流程是怎麼流的、並隨時關注數據庫表裏的數據的變化等,對以後的學習很有幫助!

2.2. 核心組件介紹

2.2.1. 關鍵對象

  1. Deployment:流程部署對象,部署一個流程時創建。

  2. ProcessDefinitions:流程定義,部署成功後自動創建。

  3. ProcessInstances:流程實例,啓動流程時創建。

  4. Task:任務,在Activiti中的Task僅指有角色參與的任務,即定義中的UserTask。

  5. Execution:執行計劃,流程實例和流程執行中的所有節點都是Execution,如UserTask、ServiceTask等。
    2.2.2. 服務接口

  6. ProcessEngine:流程引擎的抽象,通過它我們可以獲得我們需要的一切服務。

  7. RepositoryService:Activiti中每一個不同版本的業務流程的定義都需要使用一些定義文件,部署文件和支持數據(例如BPMN2.0 XML文件,表單定義文件,流程定義圖像文件等),這些文件都存儲在Activiti內建的Repository中。RepositoryService提供了對 repository的存取服務。

  8. RuntimeService:在Activiti中,每當一個流程定義被啓動一次之後,都會生成一個相應的流程對象實例。RuntimeService提供了啓動流程、查詢流程實例、設置獲取流程實例變量等功能。此外它還提供了對流程部署,流程定義和流程實例的存取服務。

  9. TaskService: 在Activiti中業務流程定義中的每一個執行節點被稱爲一個Task,對流程中的數據存取,狀態變更等操作均需要在Task中完成。TaskService提供了對用戶Task 和Form相關的操作。它提供了運行時任務查詢、領取、完成、刪除以及變量設置等功能。

  10. IdentityService: Activiti中內置了用戶以及組管理的功能,必須使用這些用戶和組的信息才能獲取到相應的Task。IdentityService提供了對Activiti 系統中的用戶和組的管理功能。

  11. ManagementService: ManagementService提供了對Activiti流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程序中使用,主要用於Activiti系統的日常維護。

  12. HistoryService: HistoryService用於獲取正在運行或已經完成的流程實例的信息,與RuntimeService中獲取的流程信息不同,歷史信息包含已經持久化存儲的永久信息,並已經被針對查詢優化。

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

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

3. 入門示例(參考手冊中10分鐘教程)

3.1. 概述

下面開始編寫一個示例。這個Demo爲一個“月度報表申請”流程。由“sales(銷售)”組的用戶製作月度報表,提交給“management(經理)”組的用戶,經理審批該報表,最後結束。流程圖如下:

這個Demo完成之後,我們會進行兩個測試。一個是代碼中的單元測試,就是跑一遍流程,看一下流程在跑的過程中輸出的信息;一個是我們將編輯好的bpmn20.xml文件通過我們之前一分鐘入門的示例activiti-explorer應用導入進去,查看它的流程圖,並完整執行一遍流程。

在編寫這個Demo之前,至少要了解Activiti與Spring如何集成、XxxService各自的任務與作用,並完成上一章的Demo。
3.2. 流程文件xxx.bpmn20.xml

首先,我們就來編寫這個流程的bpmn20.xml文件。

<definitions id="definitions"
  targetNamespace="http://activiti.org/bpmn20"
  xmlns:activiti="http://activiti.org/bpmn"
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">

        <process id="financialReport" name="Monthly financial report reminderprocess">

          <startEvent id="theStart" />

          <sequenceFlow id='flow1' sourceRef='theStart' targetRef='writeReportTask' />


          <userTask id="writeReportTask" name="Write monthly financial report" >
            <documentation>
              Write monthly financial reportfor publication to shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>sales</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id='flow2' sourceRef='writeReportTask' targetRef='verifyReportTask' />

          <userTask id="verifyReportTask" name="Verify monthly financial report" >
            <documentation>
              Verify monthly financial reportcomposed by the accountancy department.
              This financial report is goingto be sent to all the company shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>management</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id='flow3' sourceRef='verifyReportTask' targetRef='theEnd' />

          <endEvent id="theEnd" />

        </process>

</definitions>

這裏對部分代碼進行解釋。

1) 文件的開頭部分,這裏的id對於Activiti來說, 應該叫做key。創建流程實例時,會根據此id來得到這個流程。

2) 開始流程。

3) 順序流(就是連接各個節點的指向線)

sourceRef和targetRef分別爲起始節點和目標節點。

4) 描述用戶任務

id爲該用戶任務的標識。

documentation爲該用戶任務的描述。

5) 分配用戶

可以把任務分配給指定的用戶,也可以分配給指定的組,並且可以有多個,詳見用戶手冊。
3.3. Spring配置文件

這裏配置了數據源、事務管理、流程引擎及幾個必要的xxxService。這裏數據源使用的是dbcp。數據庫信息就配置成你自己本地數據庫的信息,如果不會配置。

   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

         destroy-method="close">

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

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

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

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

         <property name="initialSize" value="20" />

         <property name="maxActive" value="50"/>

         <property name="maxIdle" value="20"/>

         <property name="minIdle" value="10"/>

    </bean>



    <bean id="transactionManager"

         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <property name="dataSource" ref="dataSource"></property>

    </bean>

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

         <property name="dataSource" ref="dataSource" />

         <property name="transactionManager" ref="transactionManager" />

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

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

    </bean>



    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

         <property name="processEngineConfiguration" ref="processEngineConfiguration" />

    </bean>



    <bean id="repositoryService" factory-bean="processEngine"

         factory-method="getRepositoryService" />

    <bean id="runtimeService" factory-bean="processEngine"

         factory-method="getRuntimeService" />

    <bean id="taskService" factory-bean="processEngine"

         factory-method="getTaskService" />

    <bean id="historyService" factory-bean="processEngine"

         factory-method="getHistoryService" />

    <bean id="managementService" factory-bean="processEngine"

         factory-method="getManagementService" />



    <tx:annotation-driven transaction-manager="transactionManager" />

注:bpmn20.xml文件中用到了兩個用戶組(sales、management),是因爲我們啓動Tomcat運行activiti-explorer應用初始化時自動就會往數據庫裏添加一些數據,其中用戶組的表中就會添加幾條記錄,其中就包括這兩個組,所以不用管它怎麼來的,總之數據庫裏有這兩個組就對了。而應用默認使用的是內存數據庫,服務一停止數據也就沒有了。所以爲了進行單元測試,需要按前面講的修改數據庫配置的方法:

把activiti-explorer應用的數據庫配置改成你自己的本地數據庫的信息,我使用的是Mysql數據庫。再啓動tomcat運行應用(目的就是爲了讓數據庫有數據),這時你的本地數據庫就有數據了,可以編寫測試用例進行單元測試了。
3.4. 編寫測試用例

1) 讀取Spring配置文件,注入流程所需的Service

2) 編寫測試方法

   @Test

    public void monthtest() {

        // 部署流程定義

        repositoryService.createDeployment().addClasspathResource("myProcess.bpmn20.xml").deploy();

        // 啓動流程實例

        String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();

        // 獲得第一個任務

        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("sales").list();

        for (Task task : tasks) {

            System.out.println("Following task is available for sales group: " + task.getName());

            // 認領任務這裏由foozie認領,因爲fozzie是sales組的成員

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

        }

        // 查看fozzie現在是否能夠獲取到該任務

        tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();

        for (Task task : tasks) {

            System.out.println("Task for fozzie: " + task.getName());

            // 執行(完成)任務

            taskService.complete(task.getId());

        }

        // 現在fozzie的可執行任務數就爲0了

        System.out.println("Number of tasks for fozzie: "

                           + taskService.createTaskQuery().taskAssignee("fozzie").count());

        // 獲得第二個任務

        tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();

        for (Task task : tasks) {

            System.out.println("Following task is available for accountancy group:" + task.getName());

            // 認領任務這裏由kermit認領,因爲kermit是management組的成員

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

        }

        // 完成第二個任務結束流程

        for (Task task : tasks) {

            taskService.complete(task.getId());

        }

        // 覈實流程是否結束,輸出流程結束時間

        HistoricProcessInstancehistoricProcessInstance = historyService.createHistoricProcessInstanceQuery()

                                                                       .processInstanceId(procId).singleResult();

        System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

}

3) 運行示例,Demo完成。這就是一個最簡單的流程,通過這個流程,瞭解到Activiti中流程是怎麼流的,我們怎麼控制它。
3.5. 導入activiti-explorer

1) 單元測試完成後,我們可以將該bpmn20.xml文件導入之前我們部署的activiti-explorer應用中:點擊流程的流程設計工作區,點擊導入,將剛纔我們編寫的文件導入進去。

2) 導入之後在右上角點擊部署。

3) 在已部署流程定義中我們可以看到這個流程,及它的流程圖。

4) 點擊啓動流程,該流程就會被啓動,再點擊任務中,列隊就會有該任務了,而且是分配給sales的,這正是我們定義流程時所分配給的用戶組啊。注意,現在只有sales組的用戶纔可以看到此任務!

5) sales組的用戶進入之後點擊“簽收”,該任務就分配給該用戶了,然後該用戶就可以進行處理,也就是在代辦任務和受邀裏。

6) 進去之後點擊完成任務,該任務就流到下一個節點,也就是流轉到management組中去了,要由management組的用戶去處理。

7) 於是這時候,隊列中management組就有一個新的任務了,等待management組的成員來“簽收”,並完成任務。該流程也就結束了。

8) 此時就可以查看歷史任務了,就是我們這裏的“已歸檔”。用戶完成的任務會在這裏顯示。

這就是整個Demo的編寫、測試過程。這樣一個小小的流程基本能夠體現出Activiti的功能及使用方法。

4. Eclipse中的Activiti插件

Activiti有一個Eclipse插件,Activiti Eclipse Designer,可用於圖形化建模、測試、部署 BPMN 2.0的流程。這樣就不用我們自己去編寫繁瑣的流程文件了。具體安裝方法見手冊。
4.1. 安裝

打開 Help-> Install New Software.在如下面板中 , 點擊 Add 按鈕, 然後填入下列字段:

Name: Activiti BPMN 2.0 designer

Location: http://activiti.org/designer/update/

然後一步步的安裝就可以了。
4.2. 使用

至於如何使用,文檔中介紹的非常詳細,這裏基於我初次使用的經驗,強調幾點:

1) 安裝之後將“保存bpmn文件時創建圖片文件”勾選上。這樣你每次保存bpmn文件時,會爲你自動創建圖片文件。

2) 節點的所有屬性可在properties控制檯中設置。

3) 在使用設計器之前,先去鑽研BPNM2.0規範吧,瞭解BPNM結構(可參看用戶手冊),才能畫出符合邏輯且完美的流程圖。

該例爲使用Activiti Eclipse Designer設計的“請假”流程圖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章