http://wenku.baidu.com/view/bb7364ad4693daef5ff73d32.html
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. 服務接口
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,以及事務的處理。
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設計的“請假”流程圖。