Activiti最全入門教程

工作流(Workflow),就是“業務過程的部分或整體在計算機應用環境下的自動化”,它主要解決的是“使在多個參與者之間按照某種預定義的規則傳遞文檔、信息或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現”。 
工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,並按照在系統中預先定義好的工作流規則進行工作流實例的執行。工作流管理系統不是企業的業務系統,而是爲企業的業務系統的運行提供了一個軟件的支撐環境。 
工作流管理聯盟(WfMC,Workflow Management Coalition)給出的關於工作流管理系統的定義是:工作流管理系統是一個軟件系統,它通過執行經過計算的流程定義去支持一批專門設定的業務流程。工作流管理系統被用來定義、管理、和執行工作流程。 
工作流管理系統的目標:管理工作的流程以確保工作在正確的時間被期望的人員所執行——在自動化進行的業務過程中插入人工的執行和干預。 
3:Activiti介紹 
Activiti5是由Alfresco軟件在2010年5月17日發佈的業務流程管理(BPM)框架,它是覆蓋了業務流程管理、工作流、服務協作等領域的一個開源的、靈活的、易擴展的可執行流程語言框架。Activiti基於Apache許可的開源BPM平臺,創始人Tom Baeyens是JBoss jBPM的項目架構師,它特色是提供了eclipse插件,開發人員可以通過插件直接繪畫出業務 
流程圖。 
這裏寫圖片描述

3.1:工作流引擎 
ProcessEngine對象,這是Activiti工作的核心。負責生成流程運行時的各種實例及數據、監控和管理流程的運行。 
3.2:BPMN 
業務流程建模與標註(Business Process Model and Notation,BPMN) ,描述流程的基本符號,包括這些圖元如何組合成一個業務流程圖(Business Process Diagram)

3.3:數據庫(先了解後看) 
Activiti數據庫支持: 
Activiti的後臺是有數據庫的支持,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。 用途也和服務的API對應。 
ACT_RE_*: ‘RE’表示repository。 這個前綴的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。 
ACT_RU_*: ‘RU’表示runtime。 這些運行時的表,包含流程實例,任務,變量,異步任務,等運行中的數據。 Activiti只在流程實例執行過程中保存這些數據, 在流程結束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。 
ACT_ID_*: ‘ID’表示identity。 這些表包含身份信息,比如用戶,組等等。 
ACT_HI_*: ‘HI’表示history。 這些表包含歷史數據,比如歷史流程實例, 變量,任務等等。 
ACT_GE_*: 通用數據, 用於不同場景下,如存放資源文件。

表結構操作: 
3.3.1:資源庫流程規則表 
1) act_re_deployment 部署信息表 
2) act_re_model 流程設計模型部署表 
3) act_re_procdef 流程定義數據表 
3.3.2:運行時數據庫表 
1) act_ru_execution 運行時流程執行實例表 
2) act_ru_identitylink 運行時流程人員表,主要存儲任務節點與參與者的相關信息 
3) act_ru_task 運行時任務節點表 
4) act_ru_variable 運行時流程變量數據表 
3.3.3:歷史數據庫表 
1) act_hi_actinst 歷史節點表 
2) act_hi_attachment 歷史附件表 
3) act_ih_comment 歷史意見表 
4) act_hi_identitylink 歷史流程人員表 
5) act_hi_detail 歷史詳情表,提供歷史變量的查詢 
6) act_hi_procinst 歷史流程實例表 
7) act_hi_taskinst 歷史任務實例表 
8) act_hi_varinst 歷史變量表 
3.3.4:組織機構表 
1) act_id_group 用戶組信息表 
2) act_id_info 用戶擴展信息表 
3) act_id_membership 用戶與用戶組對應信息表 
4) act_id_user 用戶信息表 
這四張表很常見,基本的組織機構管理,關於用戶認證方面建議還是自己開發一套,組件自帶的功能太簡單,使用中有很多需求難以滿足 
3.3.5:通用數據表 
1) act_ge_bytearray 二進制數據表 
2) act_ge_property 屬性數據表存儲整個流程引擎級別的數據,初始化表結構時,會默認插入三條記錄, 
3.4:activiti.cfg.xml(activiti的配置文件) 
Activiti核心配置文件,配置流程引擎創建工具的基本參數和數據庫連接池參數。 
定義數據庫配置參數: 
 jdbcUrl: 數據庫的JDBC URL。 
 jdbcDriver: 對應不同數據庫類型的驅動。 
 jdbcUsername: 連接數據庫的用戶名。 
 jdbcPassword: 連接數據庫的密碼。 
基於JDBC參數配置的數據庫連接 會使用默認的MyBatis連接池。 下面的參數可以用來配置連接池(來自MyBatis參數): 
 jdbcMaxActiveConnections: 連接池中處於被使用狀態的連接的最大值。默認爲10。 
 jdbcMaxIdleConnections: 連接池中處於空閒狀態的連接的最大值。 
 jdbcMaxCheckoutTime: 連接被取出使用的最長時間,超過時間會被強制回收。 默認爲20000(20秒)。 
 jdbcMaxWaitTime: 這是一個底層配置,讓連接池可以在長時間無法獲得連接時, 打印一條日誌,並重新嘗試獲取一個連接。(避免因爲錯誤配置導致沉默的操作失敗)。 默認爲20000(20秒)。 
示例數據庫配置: 
這裏寫圖片描述

也可以使用javax.sql.DataSource。 (比如,Apache Commons的DBCP): 
這裏寫圖片描述 
3.5:logging.properties(日誌處理) 
日誌的配置文件,Activiti操作數據庫的時候,整合的日誌文件 
4:準備環境 
4.1:activiti5 軟件環境 
1) JDK1.6或者更高版本 
2) 支持的數據庫有:h2, mysql, oracle, postgres, mssql, db2等。 
3) 支持activiti5運行的jar包 
4) 開發環境爲Eclipse3.7或者以上版本,myeclipse爲8.6版本 
4.2:相關資源下載 
1) JDK可以到sun的官網下載 
http://www.oracle.com/technetwork/java/javase/downloads/index.html 
2) 數據庫,例如:mysql可以在官網上下載。 
http://www.mysql.com 
3) activiti也可以到Activiti官方網站下載得到。 
http://activiti.org/download.html 
4) Eclipse3.7或者MyEclipse8.6也可以到相應的網站上獲得下載。 
4.3:安裝流程設計器(eclipse插件) 
4.3.1:安裝方式一 
在有網絡的情況下,安裝流程設計器步驟如下: 
1) 打開 Help -> Install New Software. 在如下面板中: 
這裏寫圖片描述
2) 在如下Install界面板中,點擊Add按鈕: 
這裏寫圖片描述 
配置新裝插件的地址和名稱

3) 然後填入下列字段 
Name: Activiti BPMN 2.0 designer 
Location: http://activiti.org/designer/update/ 
這裏寫圖片描述 
4) 回到Install界面,在面板正中列表中把所有展示出來的項目都勾上: 
這裏寫圖片描述 
5) 點擊複選框 
在Detail部分記得選中 “Contact all updates sites..” , 因爲它會檢查所有當前安裝所需要的插件並可以被Eclipse下載.

6) 安裝完以後,點擊新建工程new->Other…打開面板,如果看到下圖內容: 
這裏寫圖片描述 
說明安裝成功了。 
4.3.2:安裝方式二 
在沒有網絡的情況下,安裝流程設計器步驟如下: 
1) 解壓老師發給大家的 壓縮包 
2) 把壓縮包中的內容放入eclipse根目錄的dropins文件夾下 
3) 重啓eclipse,點擊新建工程new->Other…打開面板,如果看到下圖內容: 
這裏寫圖片描述 
說明安裝成功了 
4.4:對流程設計器的使用說明 
打開菜單Windows->Preferences->Activiti->Save下流程流程圖片的生成方式: 
這裏寫圖片描述 
雖然流程引擎在單獨部署bpmn文件時會自動生成圖片,但在實際開發過程中,自動生成的圖片會導致和BPMN中的座標有出入,在實際項目中展示流程當前位置圖會有問題。 
所在完成以上配置後,會由我們自己來管理流程圖片。在發佈流程時把流程規則文件和流程圖片一起上傳就行了。 
4.5:準備Activiti5開發環境 
4.5.1:添加Activiti5的jar包 
在activiti-5.13->wars目錄下是一些示例項目,解壓activiti-rest項目,導入activiti-rest目錄中WEB-INF\lib下所有包。添加到classpath中。 
由於我們使用的是Mysql數據庫,Mysql數據庫的鏈接驅動Activiti官方包中並沒有提供,需要我們自己導入。手動導入mysql-connector-java.jar,添加到classpath下。 
4.5.2:初始化數據庫 
這裏寫圖片描述
在Activiti中,在創建核心的流程引擎對象時會自動建表。如果程序正常執行,mysql會自動建庫,然後創建23張表。

4.5.3:添加並制定配置文件 
在Actiiti5中定製流程必定會操作到數據庫,如果都像上面那樣寫一大段代碼會非常麻煩,所以我們可以把數據庫連接配置寫入配置文件。 
在Activiti5的官方示例中並沒有現成的配置文件,所以先得找到activiti-rest\WEB-INF\classes下有:

4.5.3.1:activiti-context.xml : 
一個類似spring結構的配置文件,清空內容後改名爲activiti.cfg.xml,用來做流程引擎的相關配置。 
按照上面代碼配置ProcessEngineConfiguration對象,主要定義數據庫的連接配置和建表策略,配置文件代碼如下: 
這裏寫圖片描述
Java代碼如下: 
這裏寫圖片描述
createProcessEngineConfigurationFromResource的參數值爲我們添加的配置文件activiti.cfg.xml的名稱,執行java代碼,流程引擎對象創建成功運行後數據庫會自動建表。

 
  1. /**使用代碼創建工作流需要的23張表*/

  2. @Test

  3. public void createTable(){

  4. ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();

  5. //連接數據庫的配置

  6. processEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");

  7. processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/shareniu?useUnicode=true&characterEncoding=utf8");

  8. processEngineConfiguration.setJdbcUsername("root");

  9. processEngineConfiguration.setJdbcPassword("root");

  10.  
  11. /**

  12. public static final String DB_SCHEMA_UPDATE_FALSE = "false";不能自動創建表,需要表存在

  13. public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";先刪除表再創建表

  14. public static final String DB_SCHEMA_UPDATE_TRUE = "true";如果表不存在,自動創建表

  15. */

  16. processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

  17. //工作流的核心對象,ProcessEnginee對象

  18. ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

  19. System.out.println("processEngine:"+processEngine);

  20. }

  21.  
  22. /**使用配置文件創建工作流需要的23張表*/

  23. @Test

  24. public void createTable_2(){

  25. // ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");

  26. // //工作流的核心對象,ProcessEnginee對象

  27. // ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

  28.  
  29. ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml") //

  30. .buildProcessEngine();

  31. System.out.println("processEngine:"+processEngine);

  32. }

4.5.3.2:log4j.properties 日誌配置文件 
把兩個文件放入resource目錄下即可。

5:核心API 
5.1:ProcessEngine 
說明: 
1) 在Activiti中最核心的類,其他的類都是由他而來。 
2) 產生方式:

在前面看到了兩種創建ProcessEngine(流程引擎)的方式,而這裏要簡化很多,調用ProcessEngines的getDefaultProceeEngine方法時會自動加載classpath下名爲activiti.cfg.xml文件。 
3) 可以產生RepositoryService

4) 可以產生RuntimeService

5) 可以產生TaskService

各個Service的作用: 
RepositoryService 管理流程定義 
RuntimeService 執行管理,包括啓動、推進、刪除流程實例等操作 
TaskService 任務管理 
HistoryService 歷史管理(執行完的數據的管理) 
IdentityService 組織機構管理 
FormService 一個可選服務,任務表單管理 
ManagerService

5.2:RepositoryService 
是Activiti的倉庫服務類。所謂的倉庫指流程定義文檔的兩個文件:bpmn文件和流程圖片。 
1) 產生方式

2) 可以產生DeploymentBuilder,用來定義流程部署的相關參數

3) 刪除流程定義

5.3:RuntimeService 
是activiti的流程執行服務類。可以從這個服務類中獲取很多關於流程執行相關的信息。 
5.4:TaskService 
是activiti的任務服務類。可以從這個類中獲取任務的信息。 
5.5:HistoryService 
是activiti的查詢歷史信息的類。在一個流程執行完成後,這個對象爲我們提供查詢歷史信息。 
5.6:ProcessDefinition 
流程定義類。可以從這裏獲得資源文件等。 
5.7:ProcessInstance 
代表流程定義的執行實例。如范冰冰請了一天的假,她就必須發出一個流程實例的申請。一個流程實例包括了所有的運行節點。我們可以利用這個對象來了解當前流程實例的進度等信息。流程實例就表示一個流程從開始到結束的最大的流程分支,即一個流程中流程實例只有一個。 
5.8:Execution 
Activiti用這個對象去描述流程執行的每一個節點。在沒有併發的情況下,Execution就是同ProcessInstance。流程按照流程定義的規則執行一次的過程,就可以表示執行對象Execution。 
如圖爲ProcessInstance的源代碼: 
這裏寫圖片描述
從源代碼中可以看出ProcessInstance就是Execution。但在現實意義上有所區別: 
這裏寫圖片描述 
在單線流程中,如上圖的貸款流程,ProcessInstance與Execution是一致的。 
這裏寫圖片描述 
這個例子有一個特點:wire money(匯錢)和archive(存檔)是併發執行的。 這個時候,總線路代表ProcessInstance,而分線路中每個活動代表Execution。 
總結: 
* 一個流程中,執行對象可以存在多個,但是流程實例只能有一個。 
* 當流程按照規則只執行一次的時候,那麼流程實例就是執行對象。

6:HelloWorld程序(模擬流程的執行) 
6.1:流程圖:

這裏寫圖片描述 
6.2:部署流程定義 
這裏寫圖片描述 
這裏使用RepositoryService部署流程定義 
addClasspathResource表示從類路徑下加載資源文件,一次只能加載一個文件 
6.3:啓動流程實例 
這裏寫圖片描述 
這裏使用RuntimeService啓動流程實例 
6.4:查看我的個人任務 
這裏寫圖片描述 
這裏使用TaskService完成任務的查詢 
6.5:完成我的個人任務 
這裏寫圖片描述 
這裏使用TaskService完成任務的辦理

7:管理流程定義 
7.1:設計流程定義文檔 
7.1.1:流程圖 
這裏寫圖片描述 
7.1.2:bpmn文件 
BPMN 2.0根節點是definitions節點。 這個元素中,可以定義多個流程定義(不過我們建議每個文件只包含一個流程定義, 可以簡化開發過程中的維護難度)。 一個空的流程定義看起來像下面這樣。注意,definitions元素 最少也要包含xmlns 和 targetNamespace的聲明。 targetNamespace可以是任意值,它用來對流程實例進行分類。 
這裏寫圖片描述 
說明:流程定義文檔有兩部分組成: 
1) bpmn文件 
流程規則文件。在部署後,每次系統啓動時都會被解析,把內容封裝成流程定義放入項目緩存中。Activiti框架結合這個xml文件自動管理流程,流程的執行就是按照bpmn文件定義的規則執行的,bpmn文件是給計算機執行用的。 
2) 展示流程圖的圖片 
在系統裏需要展示流程的進展圖片,圖片是給用戶看的。

7.2:部署流程定義(classpath路徑加載文件) 
這裏寫圖片描述 
說明: 
1) 先獲取流程引擎對象:在創建時會自動加載classpath下的activiti.cfg.xml

2) 首先獲得默認的流程引擎,通過流程引擎獲取了一個RepositoryService對象(倉庫對象) 
3) 由倉庫的服務對象產生一個部署對象配置對象,用來封裝部署操作的相關配置。 
4) 這是一個鏈式編程,在部署配置對象中設置顯示名,上傳流程定義規則文件 
5) 向數據庫表中存放流程定義的規則信息。 
6) 這一步在數據庫中將操作三張表: 
a) act_re_deployment(部署對象表) 
存放流程定義的顯示名和部署時間,每部署一次增加一條記錄。 
這裏寫圖片描述 
這裏寫圖片描述
Deployment deployment = processEngine.getRepositoryService()// 
.createDeployment().name(“入門程序”)// 
.addClasspathResource(“hello/helloworld.bpmn”)// 從classpath的資源中加載,一次只能加載一個文件 
// .addClasspathResource(“diagrams/helloworld.png”)// 
// 從classpath的資源中加載,一次只能加載一個文件 
.deploy(); 
b) act_re_procdef(流程定義表) 
存放流程定義的屬性信息,部署每個新的流程定義都會在這張表中增加一條記錄。 
注意:當流程定義的key相同的情況下,使用的是版本升級 
這裏寫圖片描述 
這裏寫圖片描述
對應的封裝類:

 
  1. public interface ProcessDefinition {

  2.  
  3. String getId();

  4. String getCategory();

  5. String getName();

  6. String getKey();

  7. String getDescription();

  8. int getVersion();

  9. String getResourceName();

  10. String getDeploymentId();

  11. String getDiagramResourceName();

  12. boolean hasStartFormKey();

  13. boolean isSuspended();

  14. }

代碼的操作: 
/* 查詢流程定義 /

 
  1. @Test

  2. public void findProcessDefinition() {

  3. List<ProcessDefinition> list = processEngine.getRepositoryService()// 與流程定義和部署對象相關的Service

  4. .createProcessDefinitionQuery()// 創建一個流程定義的查詢

  5. /** 指定查詢條件,where條件 */

  6. // .deploymentId(deploymentId)//使用部署對象ID查詢

  7. // .processDefinitionId(processDefinitionId)//使用流程定義ID查詢

  8. // .processDefinitionKey(processDefinitionKey)//使用流程定義的key查詢

  9. // .processDefinitionNameLike(processDefinitionNameLike)//使用流程定義的名稱模糊查詢

  10.  
  11. /** 排序 */

  12. .orderByProcessDefinitionVersion().asc()// 按照版本的升序排列

  13. // .orderByProcessDefinitionName().desc()//按照流程定義的名稱降序排列

  14.  
  15. /** 返回的結果集 */

  16. .list();// 返回一個集合列表,封裝流程定義

  17. // .singleResult();//返回惟一結果集

  18. // .count();//返回結果集數量

  19. // .listPage(firstResult, maxResults);//分頁查詢

  20. if (list != null && list.size() > 0) {

  21. for (ProcessDefinition pd : list) {

  22. System.out.println("流程定義ID:" + pd.getId());// 流程定義的key+版本+隨機生成數

  23. System.out.println("流程定義的名稱:" + pd.getName());// 對應helloworld.bpmn文件中的name屬性值

  24. System.out.println("流程定義的key:" + pd.getKey());// 對應helloworld.bpmn文件中的id屬性值

  25. System.out.println("流程定義的版本:" + pd.getVersion());// 當流程定義的key值相同的相同下,版本升級,默認1

  26. System.out.println("資源名稱bpmn文件:" + pd.getResourceName());

  27. System.out.println("資源名稱png文件:" + pd.getDiagramResourceName());

  28. System.out.println("部署對象ID:" + pd.getDeploymentId());

  29. System.out

  30. .println("#########################################################");

  31. }

  32. }

  33. }

程序的輸出: 
流程定義ID:helloworld:1:4 
流程定義的名稱:helloworldProcess 
流程定義的key:helloworld 
流程定義的版本:1 
資源名稱bpmn文件:hello/helloworld.bpmn 
資源名稱png文件:hello/helloworld.helloworld.png 
部署對象ID:1 
c) act_ge_bytearray(資源文件表) 
存儲流程定義相關的部署信息。即流程定義文檔的存放地。每部署一次就會增加兩條記錄,一條是關於bpmn規則文件的,一條是圖片的(如果部署時只指定了bpmn一個文件,activiti會在部署時解析bpmn文件內容自動生成流程圖)。兩個文件不是很大,都是以二進制形式存儲在數據庫中。 
這裏寫圖片描述
7.3:部署流程定義(zip格式文件) 
這裏寫圖片描述 
這裏寫圖片描述 
將 
壓縮成zip格式的文件,使用zip的輸入流用作部署流程定義

7.4:查看流程定義 
查詢流程定義的信息 
這裏寫圖片描述 
結果: 
這裏寫圖片描述 
再部署一次運行結果爲: 
這裏寫圖片描述 
可以看到流程定義的key值相同的情況下,版本是從1開始逐次升級的 
流程定義的Id是【key:版本:生成ID】 
說明: 
1) 流程定義和部署對象相關的Service都是RepositoryService。 
2) 創建流程定義查詢對象,可以在ProcessDefinitionQuery上設置查詢的相關參數 
3) 調用ProcessDefinitionQuery對象的list方法,執行查詢,獲得符合條件的流程定義列表 
4) 由運行結果可以看出: 
Key和Name的值爲:bpmn文件process節點的id和name的屬性值 
這裏寫圖片描述 
5) key屬性被用來區別不同的流程定義。 
6) 帶有特定key的流程定義第一次部署時,version爲1。之後每次部署都會在當前最高版本號上加1 
7) Id的值的生成規則爲:{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 這裏的generated-id是一個自動生成的唯一的數字 
8) 重複部署一次,deploymentId的值以一定的形式變化 
規則act_ge_property表生成 
這裏寫圖片描述 
7.5:刪除流程定義 
刪除部署到activiti中的流程定義。 
這裏寫圖片描述 
說明: 
1) 因爲刪除的是流程定義,而流程定義的部署是屬於倉庫服務的,所以應該先得到RepositoryService 
2) 如果該流程定義下沒有正在運行的流程,則可以用普通刪除。如果是有關聯的信息,用級聯刪除。項目開發中使用級聯刪除的情況比較多,刪除操作一般只開放給超級管理員使用。 
7.6:獲取流程定義文檔的資源(查看流程圖附件) 
查詢出流程定義文檔。主要查的是圖片,用於顯示流程用。 
這裏寫圖片描述 
說明: 
1) deploymentId爲流程部署ID 
2) resourceName爲act_ge_bytearray表中NAME_列的值 
3) 使用repositoryService的getDeploymentResourceNames方法可以獲取指定部署下得所有文件的名稱 
4) 使用repositoryService的getResourceAsStream方法傳入部署ID和資源圖片名稱可以獲取部署下指定名稱文件的輸入流 
5) 最後的有關IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到文件的拷貝,將資源文件以流的形式輸出到指定文件夾下 
7.7:附加功能:查詢最新版本的流程定義 
這裏寫圖片描述 
Key value保存 key 爲key value爲流程定義 
代碼: 
/*附加功能:查詢最新版本的流程定義*/

 
  1. @Test

  2. public void findLastVersionProcessDefinition(){

  3. List<ProcessDefinition> list = processEngine.getRepositoryService()//

  4. .createProcessDefinitionQuery()//

  5. .orderByProcessDefinitionVersion().asc()//使用流程定義的版本升序排列

  6. .list();

  7. /**

  8. * Map<String,ProcessDefinition>

  9. map集合的key:流程定義的key

  10. map集合的value:流程定義的對象

  11. map集合的特點:當map集合key值相同的情況下,後一次的值將替換前一次的值

  12. */

  13. Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();

  14. if(list!=null && list.size()>0){

  15. for(ProcessDefinition pd:list){

  16. map.put(pd.getKey(), pd);

  17. }

  18. }

  19. List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());

  20. if(pdList!=null && pdList.size()>0){

  21. for(ProcessDefinition pd:pdList){

  22. System.out.println("流程定義ID:"+pd.getId());//流程定義的key+版本+隨機生成數

  23. System.out.println("流程定義的名稱:"+pd.getName());//對應helloworld.bpmn文件中的name屬性值

  24. System.out.println("流程定義的key:"+pd.getKey());//對應helloworld.bpmn文件中的id屬性值

  25. System.out.println("流程定義的版本:"+pd.getVersion());//當流程定義的key值相同的相同下,版本升級,默認1

  26. System.out.println("資源名稱bpmn文件:"+pd.getResourceName());

  27. System.out.println("資源名稱png文件:"+pd.getDiagramResourceName());

  28. System.out.println("部署對象ID:"+pd.getDeploymentId());

  29. System.out.println("#########################################################");

  30. }

  31. }

  32. }

7.8:附加功能:刪除流程定義(刪除key相同的所有不同版本的流程定義) 
這裏寫圖片描述

 
  1. @Test

  2. public void deleteProcessDefinitionByKey() {

  3. // 流程定義的key

  4. String processDefinitionKey = "helloworld";

  5. // 先使用流程定義的key查詢流程定義,查詢出所有的版本

  6. List<ProcessDefinition> list = processEngine.getRepositoryService()//

  7. .createProcessDefinitionQuery()//

  8. .processDefinitionKey(processDefinitionKey).list();//

  9. // 遍歷,獲取每個流程定義的部署ID

  10. if (list != null && list.size() > 0) {

  11. for(ProcessDefinition pd:list){

  12. //獲取部署ID

  13. String deploymentId = pd.getDeploymentId();

  14. processEngine.getRepositoryService()//

  15. .deleteDeployment(deploymentId, true);

  16. }

  17. }

  18. }

7.9:總結 
Deployment 部署對象 
1、一次部署的多個文件的信息。對於不需要的流程可以刪除和修改。 
2、對應的表: 
act_re_deployment:部署對象表 
act_re_procdef:流程定義表 
act_ge_bytearray:資源文件表 
act_ge_property:主鍵生成策略表

ProcessDefinition 流程定義 
1、解析.bpmn後得到的流程定義規則的信息,工作流系統就是按照流程定義的規則執行的。

8:流程實例、任務的執行 
8.1:流程圖 
這裏寫圖片描述 
8.2:部署流程定義 
這裏寫圖片描述 
8.3:啓動流程實例 
這裏寫圖片描述
說明: 
1) 操作數據庫的act_ru_execution表,如果是用戶任務節點,同時也會在act_ru_task添加一條記錄 
act_ru_execution表,#正在執行的執行對象表 任務結束的之前只有 一個 變化的字段是act_id 
這裏寫圖片描述
這裏寫圖片描述

8.4:查詢我的個人任務 
這裏寫圖片描述

 
  1. @Test

  2. public void findMyPersonalTask(){

  3. String assignee = "王五";

  4. List<Task> list = processEngine.getTaskService()//與正在執行的任務管理相關的Service

  5. .createTaskQuery()//創建任務查詢對象

  6. /**查詢條件(where部分)*/

  7. .taskAssignee(assignee)//指定個人任務查詢,指定辦理人

  8. // .taskCandidateUser(candidateUser)//組任務的辦理人查詢

  9. // .processDefinitionId(processDefinitionId)//使用流程定義ID查詢

  10. // .processInstanceId(processInstanceId)//使用流程實例ID查詢

  11. // .executionId(executionId)//使用執行對象ID查詢

  12. /**排序*/

  13. .orderByTaskCreateTime().asc()//使用創建時間的升序排列

  14. /**返回結果集*/

  15. // .singleResult()//返回惟一結果集

  16. // .count()//返回結果集的數量

  17. // .listPage(firstResult, maxResults);//分頁查詢

  18. .list();//返回列表

  19. if(list!=null && list.size()>0){

  20. for(Task task:list){

  21. System.out.println("任務ID:"+task.getId());

  22. System.out.println("任務名稱:"+task.getName());

  23. System.out.println("任務的創建時間:"+task.getCreateTime());

  24. System.out.println("任務的辦理人:"+task.getAssignee());

  25. System.out.println("流程實例ID:"+task.getProcessInstanceId());

  26. System.out.println("執行對象ID:"+task.getExecutionId());

  27. System.out.println("流程定義ID:"+task.getProcessDefinitionId());

  28. System.out.println("########################################################");

  29. }

  30. }

  31. }

輸出: 
任務ID:504 
任務名稱:提交申請 
任務的創建時間:Sat Aug 09 08:50:20 CST 2014 
任務的辦理人:張三 
流程實例ID:501 
執行對象ID:501 
流程定義ID:helloworld:1:404 
接口:

 
  1. public interface Task {

  2. int DEFAULT_PRIORITY = 50;

  3. String getId(); String getName();

  4. void setName(String name);

  5. String getDescription();

  6. void setDescription(String description);

  7. int getPriority();

  8. void setPriority(int priority);

  9. String getOwner();

  10. void setOwner(String owner);

  11. String getAssignee();

  12. void setAssignee(String assignee); DelegationState getDelegationState();

  13. void setDelegationState(DelegationState delegationState);

  14. String getProcessInstanceId();

  15. String getExecutionId();

  16. String getProcessDefinitionId();

  17. Date getCreateTime();

  18. String getTaskDefinitionKey();

  19. Date getDueDate();

  20. void setDueDate(Date dueDate);

  21. void delegate(String userId);

  22. void setParentTaskId(String parentTaskId);

  23. String getParentTaskId();

  24. boolean isSuspended();

  25. Map<String, Object> getTaskLocalVariables();

  26. Map<String, Object> getProcessVariables();

  27. }

說明: 
1) 因爲是任務查詢,所以從processEngine中應該得到TaskService 
2) 使用TaskService獲取到任務查詢對象TaskQuery 
3) 爲查詢對象添加查詢過濾條件,使用taskAssignee指定任務的辦理者(即查詢指定用戶的代辦任務),同時可以添加分頁排序等過濾條件 
4) 調用list方法執行查詢,返回辦理者爲指定用戶的任務列表 
5) 任務ID、名稱、辦理人、創建時間可以從act_ru_task表中查到。 
6) Execution與ProcessInstance見5.6和5.7章節的介紹。在這種情況下,ProcessInstance相當於Execution 
7) 如果assignee屬性爲部門經理,結果爲空。因爲現在流程只到了”填寫請假申請”階段,後面的任務還沒有執行,即在數據庫中沒有部門經理可以辦理的任務,所以查詢不到。 
8) 一個Task節點和Execution節點是1對1的情況,在task對象中使用Execution_來表示他們之間的關係 
9) 任務ID在數據庫表act_ru_task中對應“ID_”列

附加: 
在activiti任務中,主要分爲兩大類查詢任務(個人任務和組任務): 
1.確切指定了辦理者的任務,這個任務將成爲指定者的私有任務,即個人任務。 
2.無法指定具體的某一個人來辦理的任務,可以把任務分配給幾個人或者一到 多個小組,讓這個範圍內的用戶可以選擇性(如有空餘時間時)來辦理這類任務,即組任務。 
先知道個人任務的查詢和辦理,組任務的操作後面講

8.5:辦理任務 
這裏寫圖片描述

說明: 
1) 是辦理任務,所以從ProcessEngine得到的是TaskService。 
2) 當執行完這段代碼,再以員工的身份去執行查詢的時候,會發現這個時候已經沒有數據了,因爲正在執行的任務中沒有數據。 
3) 對於執行完的任務,activiti將從act_ru_task表中刪除該任務,下一個任務會被插入進來。 
4) 以”部門經理”的身份進行查詢,可以查到結果。因爲流程執行到部門經理審批這個節點了。 
5) 再執行辦理任務代碼,執行完以後以”部門經理”身份進行查詢,沒有結果。 
6) 重複第3和4步直到流程執行完。 
act_ru_task表: 
這裏寫圖片描述

8.6:查詢流程狀態(判斷流程正在執行,還是結束) 
這裏寫圖片描述 
/* 查詢流程狀態(判斷流程正在執行,還是結束) /

 
  1. @Test

  2. public void isProcessEnd() {

  3. String processInstanceId = "501";

  4. ProcessInstance pi = processEngine.getRuntimeService()// 表示正在執行的流程實例和執行對象

  5. .createProcessInstanceQuery()// 創建流程實例查詢

  6. .processInstanceId(processInstanceId)// 使用流程實例ID查詢

  7. .singleResult();

  8. if (pi == null) {

  9. System.out.println("流程已經結束");

  10. } else {

  11. System.out.println("流程沒有結束");

  12. }

  13. }

 
  1. 在流程執行的過程中,創建的流程實例ID在整個過程中都不會變,當流程結束後,流程實例將會在正在執行的執行對象表中(act_ru_execution)被刪除

  2. 說明:

1) 因爲是查詢流程實例,所以先獲取runtimeService 
2) 創建流程實例查詢對象,設置實例ID過濾參數 
3) 由於一個流程實例ID只對應一個實例,使用singleResult執行查詢返回一個唯一的結果,如果結果數量大於1,則拋出異常 
4) 判斷指定ID的實例是否存在,如果結果爲空,則代表流程結束,實例在正在執行的執行對象表中已被刪除,轉換成歷史數據。 
8.7:附加功能:查詢歷史任務(後面講) 
這裏寫圖片描述 
/*查詢歷史任務(後面講)/

 
  1. @Test

  2. public void findHistoryTask(){

  3. String taskAssignee = "張三";

  4. List<HistoricTaskInstance> list = processEngine.getHistoryService()//與歷史數據(歷史表)相關的Service

  5. .createHistoricTaskInstanceQuery()//創建歷史任務實例查詢

  6. .taskAssignee(taskAssignee)//指定歷史任務的辦理人

  7. .list();

  8. if(list!=null && list.size()>0){

  9. for(HistoricTaskInstance hti:list){

  10. System.out.println(hti.getId()+" "+hti.getName()+" "+hti.getProcessInstanceId()+" "+hti.getStartTime()+" "+hti.getEndTime()+" "+hti.getDurationInMillis());

  11. System.out.println("################################");

  12. }

  13. }

  14. }

表《HistoricTaskInstance》 
8.8:附加功能:查詢歷史流程實例(後面講)

這裏寫圖片描述 
8.9:總結 
Execution 執行對象 
按流程定義的規則執行一次的過程. 
對應的表: 
act_ru_execution: 正在執行的信息 
act_hi_procinst:已經執行完的歷史流程實例信息 
act_hi_actinst:存放歷史所有完成的活動 
ProcessInstance 流程實例 
特指流程從開始到結束的那個最大的執行分支,一個執行的流程中,流程實例只有1個。

注意 
(1)如果是單例流程,執行對象ID就是流程實例ID 
(2)如果一個流程有分支和聚合,那麼執行對象ID和流程實例ID就不相同 
(3)一個流程中,流程實例只有1個,執行對象可以存在多個。

Task 任務 
執行到某任務環節時生成的任務信息。 
對應的表: 
act_ru_task:正在執行的任務信息 
act_hi_taskinst:已經執行完的歷史任務信息

9:流程變量 
9.1:流程圖 
這裏寫圖片描述 
流程變量在整個工作流中扮演很重要的作用。例如:請假流程中有請假天數、請假原因等一些參數都爲流程變量的範圍。流程變量的作用域範圍是只對應一個流程實例。也就是說各個流程實例的流程變量是不相互影響的。流程實例結束完成以後流程變量還保存在數據庫中。 
例如: 
這裏寫圖片描述
即:

9.2:部署流程定義 
這裏寫圖片描述 
說明: 
• 輸入流加載資源文件的3種方式 
這裏寫圖片描述 
這裏寫圖片描述

9.3:啓動流程實例 
這裏寫圖片描述 
9.4:設置流程變量 
這裏寫圖片描述
說明: 
1) 流程變量的作用域就是流程實例,所以只要設置就行了,不用管在哪個階段設置 
2) 基本類型設置流程變量,在taskService中使用任務ID,定義流程變量的名稱,設置流程變量的值。 
3) Javabean類型設置流程變量,需要這個javabean實現了Serializable接口 
4) 設置流程變量的時候,向act_ru_variable這個表添加數據

9.5:獲取流程變量 
這裏寫圖片描述

說明: 
1) 流程變量的獲取針對流程實例(即1個流程),每個流程實例獲取的流程變量時不同的 
2) 使用基本類型獲取流程變量,在taskService中使用任務ID,流程變量的名稱,獲取流程變量的值。 
3) Javabean類型設置獲取流程變量,除了需要這個javabean實現了Serializable接口外,還要求流程變量對象的屬性不能發生變化,否則拋出異常。 
解決方案,在javabean對象中添加: 
private static final long serialVersionUID = 6757393795687480331L; 
9.6:模擬流程變量的設置和獲取的場景 
這裏寫圖片描述 
說明: 
1) RuntimeService對象可以設置流程變量和獲取流程變量 
2) TaskService對象可以設置流程變量和獲取流程變量 
3) 流程實例啓動的時候可以設置流程變量 
4) 任務辦理完成的時候可以設置流程變量 
5) 流程變量可以通過名稱/值的形式設置單個流程變量 
6) 流程變量可以通過Map集合,同時設置多個流程變量 
Map集合的key表示流程變量的名稱 
Map集合的value表示流程變量的值

9.7:查詢歷史的流程變量 
這裏寫圖片描述 
說明: 
1)歷史的流程變量查詢,指定流程變量的名稱,查詢act_hi_varinst表(也可以針對,流程實例ID,執行對象ID,任務ID查詢)

9.8:流程變量的支持的類型 
如圖是從官網列出來的流程變量的類型: 
這裏寫圖片描述 
從圖中可以看出包括了大部分封裝類型和Date、String和實現了Serializable接口的類的類型。 
9.9:總結 
• 1:流程變量 
在流程執行或者任務執行的過程中,用於設置和獲取變量,使用流程變量在流程傳遞的過程中傳遞業務參數。 
對應的表: 
act_ru_variable:正在執行的流程變量表 
act_hi_varinst:流程變量歷史表

• 2:擴展知識:setVariable和setVariableLocal的區別 
setVariable:設置流程變量的時候,流程變量名稱相同的時候,後一次的值替換前一次的值,而且可以看到TASK_ID的字段不會存放任務ID的值 
setVariableLocal: 
1:設置流程變量的時候,針對當前活動的節點設置流程變量,如果一個流程中存在2個活動節點,對每個活動節點都設置流程變量,即使流程變量的名稱相同,後一次的版本的值也不會替換前一次版本的值,它會使用不同的任務ID作爲標識,存放2個流程變量值,而且可以看到TASK_ID的字段會存放任務ID的值 
例如act_hi_varinst 表的數據:不同的任務節點,即使流程變量名稱相同,存放的值也是不同的。 
如圖: 
這裏寫圖片描述
2:還有,使用setVariableLocal說明流程變量綁定了當前的任務,當流程繼續執行時,下個任務獲取不到這個流程變量(因爲正在執行的流程變量中沒有這個數據),所有查詢正在執行的任務時不能查詢到我們需要的數據,此時需要查詢歷史的流程變量。

10:流程執行歷史記錄 
10.1:查詢歷史流程實例 
查找按照某個流程定義的規則一共執行了多少次流程 
這裏寫圖片描述 
10.2:查詢歷史活動 
某一次流程的執行一共經歷了多少個活動 
這裏寫圖片描述 
10.3:查詢歷史任務 
某一次流程的執行一共經歷了多少個任務 
這裏寫圖片描述 
10.4:查詢歷史流程變量 
某一次流程的執行一共設置的流程變量 
這裏寫圖片描述 
10.5:總結 
由於數據庫中保存着歷史信息以及正在運行的流程實例信息,在實際項目中對已完成任務的查看頻率遠不及對代辦和可接任務的查看,所以在activiti採用分開管理,把正在運行的交給RuntimeService、TaskService管理,而歷史數據交給HistoryService來管理。 
這樣做的好處在於,加快流程執行的速度,因爲正在執行的流程的表中數據不會很大。

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