1. 程式人生 > >Activiti 入門:10分鐘的教程

Activiti 入門:10分鐘的教程

7.3。入門:10分鐘的教程

在本節中,我們將介紹一個(非常簡單的)業務流程,我們將使用它來介紹一些基本的Activiti概念和Activiti API。

7.3.1。先決條件

本教程假設您正在執行Activiti演示設定,並且您正在使用獨立的H2伺服器。編輯db.properties並設定jdbc.url=jdbc:h2:tcp://localhost/activiti,然後根據H2的文件執行獨立伺服器。

7.3.2。目標

本教程的目標是瞭解Activiti和一些基本的BPMN 2.0概念。最終結果將是一個簡單的Java SE程式,它部署流程定義,並通過Activiti引擎API與此流程互動。我們還將觸及Activiti周圍的一些工具。當然,在圍繞業務流程構建自己的Web應用程式時,也可以使用本教程中學到的內容。

7.3.3。用例

用例很簡單:我們有一家公司,我們稱之為BPMCorp。在BPMCorp,每個月都需要為公司股東撰寫財務報告。這是會計部門的責任。報告完成後,高層管理人員中的一位成員需要在將檔案傳送給所有股東之前批准該檔案。

7.3.4。流程圖

可以使用Activiti Designer以圖形方式顯示上述業務流程 。但是,對於本教程,我們將自己鍵入XML,因為我們在這一點上以這種方式學習最多。我們流程的圖形化BPMN 2.0表示法如下所示:

financial.report.example.diagram

我們看到的是無啟動事件(左側的圓圈),然後是兩個使用者任務“編寫月度財務報告”和 “驗證月度財務報告”,以無終止事件結束(右側帶有粗邊框的圓圈) 。

7.3.5。XML表示

此業務流程的XML版本(FinancialReportProcess.bpmn20.xml)如下所示。很容易識別我們流程的主要元素(點選連結轉到該BPMN 2.0構造的詳細部分):

  • (無)啟動事件告訴我們什麼入口點的過程。

  • 使用者任務宣告是我們的過程的人工任務的表示。請注意,第一個任務分配給會計組,而第二個任務分配給管理組。有關如何將使用者和組分配給使用者任務的詳細資訊,請參閱有關使用者任務分配的部分

  • 當達到無結束事件時,該過程結束。

  • 元素通過順序流相互連線。這些序列流具有a sourcetarget定義序列流的方向

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

<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 reminder process"> <startEvent id="theStart" /> <sequenceFlow id="flow1" sourceRef="theStart" targetRef="writeReportTask" /> <userTask id="writeReportTask" name="Write monthly financial report" > <documentation> Write monthly financial report for publication to shareholders. </documentation> <potentialOwner> <resourceAssignmentExpression> <formalExpression>accountancy</formalExpression> </resourceAssignmentExpression> </potentialOwner> </userTask> <sequenceFlow id="flow2" sourceRef="writeReportTask" targetRef="verifyReportTask" /> <userTask id="verifyReportTask" name="Verify monthly financial report" > <documentation> Verify monthly financial report composed by the accountancy department. This financial report is going to 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>

7.3.6。啟動流程例項

我們現在已經建立了業務流程的流程定義。從這樣的流程定義中,我們可以建立流程例項。在這種情況下,一個流程例項將與特定月份的單個財務報告的建立和驗證相匹配。所有流程例項共享相同的流程定義。

為了能夠從給定的流程定義建立流程例項,我們必須首先部署此流程定義。部署流程定義意味著兩件事:

  • 流程定義將儲存在為Activiti引擎配置的持久資料儲存中。因此,通過部署我們的業務流程,我們確保引擎在引擎重啟後找到流程定義。

  • BPMN 2.0流程檔案將被解析為記憶體中的物件模型,該模型可以通過Activiti API進行操作。

有關部署的更多資訊,請參閱有關部署的專用部分

如該部分所述,部署可以通過多種方式進行。一種方法是通過API如下。請注意,與Activiti引擎的所有互動都通過其服務進行

1 2 3

Deployment deployment = repositoryService.createDeployment() .addClasspathResource("FinancialReportProcess.bpmn20.xml") .deploy();

現在,我們可以使用id流程定義中定義的流程例項啟動新的流程例項(請參閱XML檔案中的流程元素)。請注意,idActiviti術語中的這個稱為金鑰

1

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");

這將建立一個首先通過start事件的流程例項。在啟動事件之後,它遵循所有傳出的順序流(在這種情況下只有一個)並且達到第一個任務(寫月度財務報告)。Activiti引擎現在將任務儲存在持久資料庫中。此時,附加到任務的使用者或組分配將被解析並存儲在資料庫中。值得注意的是,Activiti引擎將繼續執行流程執行步驟,直到達到等待狀態,例如使用者任務。在這種等待狀態下,流程例項的當前狀態儲存在資料庫中。在使用者決定完成任務之前,它仍處於該狀態。此時,引擎將繼續執行,直到達到新的等待狀態或程序結束。當引擎在此期間重新啟動或崩潰時,該過程的狀態在資料庫中是安全的。

建立任務後,該startProcessInstanceByKey方法將返回,因為使用者任務活動是等待狀態。在這種情況下,任務被分配給一個組,這意味著該組的每個成員都是執行該任務的候選者。

我們現在可以將所有這些放在一起並建立一個簡單的Java程式。建立一個新的Eclipse專案,並將Activiti JAR和依賴項新增到其類路徑中(這些可以在Activiti發行版的libs資料夾中找到)。在我們呼叫Activiti服務之前,我們必須首先構建一個ProcessEngine允許我們訪問服務的服務。這裡我們使用'standalone'配置,它構造一個ProcessEngine使用也在演示設定中使用的資料庫。

您可以在此處下載流程定義XML 。此檔案包含如上所示的XML,但還包含必要的BPMN 圖交換資訊,以便在Activiti工具中視覺化該過程。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

public static void main(String[] args) { // Create Activiti process engine ProcessEngine processEngine = ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration() .buildProcessEngine(); // Get Activiti services RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); // Deploy the process definition repositoryService.createDeployment() .addClasspathResource("FinancialReportProcess.bpmn20.xml") .deploy(); // Start a process instance runtimeService.startProcessInstanceByKey("financialReport"); }

7.3.7。任務列表

我們現在可以TaskService通過新增以下邏輯來檢索此任務:

1

List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list();

請注意,我們傳遞給此操作的使用者需要是會計組的成員,因為它是在流程定義中宣告的:

1 2 3 4 5

<potentialOwner> <resourceAssignmentExpression> <formalExpression>accountancy</formalExpression> </resourceAssignmentExpression> </potentialOwner>

我們還可以使用任務查詢API來使用組的名稱獲得相同的結果。我們現在可以在程式碼中新增以下邏輯:

1 2

TaskService taskService = processEngine.getTaskService(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();

由於我們已經將我們配置ProcessEngine為使用與演示設定正在使用的相同的資料庫,因此我們現在可以登入到Activiti Explorer。預設情況下,沒有使用者在會計組中。使用kermit / kermit登入,單擊“組”,然後單擊“建立組”。然後單擊“使用者”並將該組新增到fozzie。現在使用fozzie / fozzie登入,我們會發現在選擇“ 流程”頁面並單擊“每月財務報告”流程對應的“操作”列中的“啟動流程”連結後,我們就可以啟動業務流程。

bpmn.financial.report.example.start.process

如上所述,該過程將執行第一個使用者任務。由於我們以kermit身份登入,因此我們可以看到在我們啟動流程例項後,有一個新的候選任務可供他使用。選擇“ 任務”頁面以檢視此新任務。請注意,即使該程序是由其他人啟動的,該任務仍然可以作為候選任務顯示給會計組中的每個人。

bpmn.financial.report.example.task.assigned

7.3.8。聲稱任務

會計師現在需要申領任務。通過宣告任務,特定使用者將成為任務的受讓人,並且任務將從會計組的其他成員的每個任務列表中消失。宣告任務是以程式設計方式完成的,如下所示:

1

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

該任務現在位於宣告任務個人任務列表中

1

List<Task> tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();

在Activiti UI App中,單擊宣告按鈕將呼叫相同的操作。該任務現在將移至登入使用者的個人任務列表。您還會看到任務的受理人已更改為當前登入的使用者。

bpmn.financial.report.example.claim.task

7.3.9。完成任務

會計師現在可以開始編制財務報告。報告完成後,他可以完成任務,這意味著完成該任務的所有工作。

1

taskService.complete(task.getId());

對於Activiti引擎,這是一個外部訊號,必須繼續執行流程例項。任務本身將從執行時資料中刪除。遵循任務的單個傳出轉換,將執行移至第二個任務(“報告驗證”)。現在將使用與第一個任務描述的機制相同的機制來分配第二個任務,但差異很小,即任務將分配給 管理組。

在演示設定中,單擊任務列表中的完整按鈕即可完成任務。由於Fozzie不是會計師,我們需要退出Activiti Explorer並以kermit(誰是經理)身份登入。現在,第二個任務在未分配的任務列表中可見。

7.3.10。結束這個過程

可以以與以前完全相同的方式檢索和宣告驗證任務。完成第二個任務會將流程執行移至結束事件,從而完成流程例項。將從資料儲存中刪除流程例項和所有相關的執行時執行資料。

當您登入Activiti Explorer時,您可以對此進行驗證,因為在儲存流程執行的表中不會找到任何記錄。

bpmn.financial.report.example.process.ended

以程式設計方式,您還可以使用以下命令驗證程序是否已結束 historyService

1 2 3 4

HistoryService historyService = processEngine.getHistoryService(); HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult(); System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

7.3.11。程式碼概述

結合前面部分的所有片段,你應該有這樣的東西(這段程式碼考慮到你可能會通過Activiti Explorer UI啟動一些流程例項。因此,它總是檢索一個任務列表而不是一個任務,所以它總是有效):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

public class TenMinuteTutorial { public static void main(String[] args) { // Create Activiti process engine ProcessEngine processEngine = ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration() .buildProcessEngine(); // Get Activiti services RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); // Deploy the process definition repositoryService.createDeployment() .addClasspathResource("FinancialReportProcess.bpmn20.xml") .deploy(); // Start a process instance String procId = runtimeService.startProcessInstanceByKey("financialReport").getId(); // Get the first task TaskService taskService = processEngine.getTaskService(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list(); for (Task task : tasks) { System.out.println("Following task is available for accountancy group: " + task.getName()); // claim it taskService.claim(task.getId(), "fozzie"); } // Verify Fozzie can now retrieve the task tasks = taskService.createTaskQuery().taskAssignee("fozzie").list(); for (Task task : tasks) { System.out.println("Task for fozzie: " + task.getName()); // Complete the task taskService.complete(task.getId()); } System.out.println("Number of tasks for fozzie: " + taskService.createTaskQuery().taskAssignee("fozzie").count()); // Retrieve and claim the second task tasks = taskService.createTaskQuery().taskCandidateGroup("management").list(); for (Task task : tasks) { System.out.println("Following task is available for management group: " + task.getName()); taskService.claim(task.getId(), "kermit"); } // Completing the second task ends the process for (Task task : tasks) { taskService.complete(task.getId()); } // verify that the process is actually finished HistoryService historyService = processEngine.getHistoryService(); HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult(); System.out.println("Process instance end time: " + historicProcessInstance.getEndTime()); } }

7.3.12。未來的改進

很容易看出這個業務流程太簡單,無法在現實中使用。但是,當您瀏覽Activiti中提供的BPMN 2.0構造時,您將能夠通過以下方式增強業務流程:

  • 定義充當決策的閘道器。這樣,經理可以拒絕重建會計任務的財務報告。

  • 宣告和使用變數,以便我們可以儲存或引用報表,以便可以在表單中顯示它。

  • 在流程結束時定義服務任務,將任務傳送給每個股東。

  • 等等