自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

jBPM4實(shí)現(xiàn)基本活動(dòng)(下)

開發(fā) 后端
這一章解釋了流程定義的基礎(chǔ),流程虛擬機(jī)給予的功能 以及活動(dòng)實(shí)現(xiàn)是如何構(gòu)建的。 同時(shí),客戶端API被用來執(zhí)行包含了那些活動(dòng)實(shí)現(xiàn)的流程。

5.5. 基本流程執(zhí)行

在下一個(gè)例子里,我們會(huì)結(jié)合自動(dòng)活動(dòng)和等待狀態(tài)。 這里例子構(gòu)建了貸款審批流程,使用WaitState 和Display活動(dòng),我們剛剛創(chuàng)建的。 貸款流程的圖形看起來像這樣:
貸款流程

貸款流程 

圖 5.3. 貸款流程

使用Java構(gòu)建流程圖形是很乏味的事情, 因?yàn)槟惚仨氃诰植孔兞恐懈櫵械囊谩?為了解決這個(gè)問題,流程虛擬機(jī)提供了一個(gè)ProcessFactory。 ProcessFactory是一種領(lǐng)域特定語言(DSL),可以嵌入到Java中, 簡化流程圖形的結(jié)構(gòu)。這個(gè)模型也叫做 流暢接口。

  1. ClientProcessDefinition processDefinition = ProcessFactory.build("loan")   
  2.   .activity("submit loan request").initial().behaviour(new Display("loan request submitted"))   
  3.     .transition().to("evaluate")   
  4.   .activity("evaluate").behaviour(new WaitState())   
  5.     .transition("approve").to("wire money")   
  6.     .transition("reject").to("end")   
  7.   .activity("wire money").behaviour(new Display("wire the money"))   
  8.     .transition().to("archive")   
  9.   .activity("archive").behaviour(new WaitState())   
  10.     .transition().to("end")   
  11.   .activity("end").behaviour(new WaitState())   
  12. .done();  

為了了解ProcessFactory的更多細(xì)節(jié),可以參考 api文檔。 ProcessFactory的另一種選擇是創(chuàng)建一個(gè)XML語言和一個(gè)XML解析器,來表示流程。 XML解析器可以直接實(shí)例化 org.jbpm.pvm.internal.model包中的類。 這種方式一般都被流程語言選擇使用。

初始化活動(dòng)submit loan request和 wire the money活動(dòng)是自動(dòng)活動(dòng)。 在這個(gè)例子中,wire the money活動(dòng)的 Display實(shí)現(xiàn) 使用Java API來把信息輸出到控制臺(tái)上。但是讀取器可以想象一個(gè)可選的 Activity實(shí)現(xiàn),使用支付流程庫的Java API 來實(shí)現(xiàn)一個(gè)真實(shí)的自動(dòng)支付。

上述流程的一個(gè)新執(zhí)行可以像下面這樣啟動(dòng)

ClientExecution execution = processDefinition.startProcessInstance();

當(dāng)startExecution方法返回時(shí), submit loan request活動(dòng)會(huì)被執(zhí)行, 執(zhí)行會(huì)位于evaluate活動(dòng)。
位于'evaluate'活動(dòng)的執(zhí)行

位于evaluate活動(dòng)的執(zhí)行 

圖 5.4. 位于'evaluate'活動(dòng)的執(zhí)行

現(xiàn)在,執(zhí)行處在一個(gè)很有趣的點(diǎn)。這里有兩個(gè)轉(zhuǎn)移從evaluate指向外邊。 一個(gè)轉(zhuǎn)移叫approve 一個(gè)轉(zhuǎn)移叫reject。像我們上面解釋的, WaitState實(shí)現(xiàn)會(huì)根據(jù)執(zhí)行的signal選擇轉(zhuǎn)移。 讓我們像這樣執(zhí)行'approve' signal:

execution.signal("approve");

這個(gè)approve signal會(huì)導(dǎo)致執(zhí)行選擇approve轉(zhuǎn)移 它會(huì)到達(dá)wire money活動(dòng)。

在wire money活動(dòng)中,信息會(huì)打印到控制臺(tái)里。 因?yàn)镈isplay沒有調(diào)用execution.waitForSignal(), 也沒有調(diào)用其他執(zhí)行傳播方法, 默認(rèn)流程行為只會(huì)讓執(zhí)行繼續(xù), 使用向外的轉(zhuǎn)移到達(dá)archive活動(dòng), 這也是一個(gè)WaitState。
位于'archive'活動(dòng)的執(zhí)行

位于archive活動(dòng)的執(zhí)行 

圖 5.5. 位于'archive'活動(dòng)的執(zhí)行

所以只有當(dāng)archive到達(dá)時(shí), signal("approve")會(huì)返回。

另一個(gè)signal就像這樣:

  1. execution.signal("approve");  

將讓執(zhí)行最終到達(dá)結(jié)束狀態(tài)。
位于'end'活動(dòng)的執(zhí)行

位于end活動(dòng)的執(zhí)行 

圖 5.6. 位于'end'活動(dòng)的執(zhí)行

5.6. 事件

事件位于流程定義中, 一系列的EventListener可以進(jìn)行注冊。

  1. public interface EventListener extends Serializable {   
  2.  
  3.   void notify(EventListenerExecution execution) throws Exception;   
  4.  
  5. }   

事件的目的是讓開發(fā)者可以為流程添加程序邏輯, 不必改變流程圖。 這是非常有價(jià)值的機(jī)制,可以促進(jìn)業(yè)務(wù)分析人員和開發(fā)者之間的協(xié)作。 業(yè)務(wù)分析人員負(fù)責(zé)描述需求。 當(dāng)他們使用流程圖歸檔那些需求, 開發(fā)者可以獲得這些圖形,讓它可執(zhí)行化。 事件會(huì)非常方便,向一個(gè)流程中添加技術(shù)細(xì)節(jié)(比如一些數(shù)據(jù)庫插入操作) 這些都是業(yè)務(wù)分析人員不感興趣的東西。

最常用的事件是由執(zhí)行自動(dòng)觸發(fā)的:

TODO: 在用戶手冊中解釋事件

事件是由流程元素和事件名稱結(jié)合而成。 用戶和流程語言也可以出發(fā)事件, 使用編程的方式在流程中使用fire方法。

  1. public interface Execution extends Serializable {   
  2.   ...   
  3.   void fire(String eventName, ProcessElement eventSource);   
  4.   ...   
  5. }  

可以把一系列的EventListeners分配給一個(gè)事件。 但是事件監(jiān)聽器不能控制執(zhí)行的流向, 因?yàn)樗鼈儍H僅是監(jiān)聽已經(jīng)執(zhí)行了的執(zhí)行。 這與活動(dòng)處理活動(dòng)的行為是不同的。 活動(dòng)行為可以響應(yīng)執(zhí)行的傳播。

我們會(huì)創(chuàng)建一個(gè)PrintLn事件監(jiān)聽器, 這與上面的Display活動(dòng)是非常相似的。

  1. public class PrintLn implements EventListener {   
  2.  
  3.   String message;   
  4.  
  5.   public PrintLn(String message) {   
  6.     this.message = message;   
  7.   }   
  8.  
  9.   public void notify(EventListenerExecution execution) throws Exception {   
  10.     System.out.println("message");   
  11.   }   
  12. }   

多個(gè)PrintLn監(jiān)聽器 會(huì)在流程中注冊。
PrintLn監(jiān)聽器流程

PrintLn監(jiān)聽器流程  

圖 5.7. PrintLn監(jiān)聽器流程

  1. ClientProcessDefinition processDefinition = ProcessFactory.build()   
  2.   .activity("a").initial().behaviour(new AutomaticActivity())   
  3.     .event("end")   
  4.       .listener(new PrintLn("leaving a"))   
  5.       .listener(new PrintLn("second message while leaving a"))   
  6.     .transition().to("b")   
  7.       .listener(new PrintLn("taking transition"))   
  8.   .activity("b").behaviour(new WaitState())   
  9.     .event("start")   
  10.       .listener(new PrintLn("entering b"))   
  11. .done();  

***個(gè)事件演示如何為相同的事件注冊多個(gè)監(jiān)聽器。 它們會(huì)根據(jù)它們指定的順序依次執(zhí)行。

然后,在轉(zhuǎn)椅上,這里的事件只有一種類型。 所以在那種情況下,事件類型不需要指定, 監(jiān)聽器可以直接添加到轉(zhuǎn)移上。

一個(gè)監(jiān)聽器每次都會(huì)執(zhí)行,當(dāng)一個(gè)執(zhí)行觸發(fā)事件時(shí),如果這個(gè)監(jiān)聽器被注冊了。 執(zhí)行會(huì)作為一個(gè)參數(shù)提供給活動(dòng)接口, 除了控制流程傳播的方法以外, 都可以被監(jiān)聽器使用。

5.7. 事件傳播

事件會(huì)默認(rèn)傳播給最近的流程元素。 目的是允許監(jiān)聽器在流程定義或組合活動(dòng)中 可以執(zhí)行所有發(fā)生在流程元素中的事件。 比如這個(gè)功能允許為end事件在流程定義或一個(gè)組合活動(dòng)中注冊一個(gè)事件監(jiān)聽器。 這種動(dòng)作會(huì)被執(zhí)行,如果一個(gè)活動(dòng)離開。 如果事件監(jiān)聽器被注冊到一個(gè)組合活動(dòng)中, 它也會(huì)被所有活動(dòng)執(zhí)行,當(dāng)組合活動(dòng)中出現(xiàn)了離開事件。

為了清楚地顯示這個(gè),我們會(huì)創(chuàng)建一個(gè)DisplaySource事件監(jiān)聽器, 這會(huì)把leaving信息和事件源 打印到控制臺(tái)。

  1. public class DisplaySource implements EventListener {   
  2.  
  3.   public void execute(EventListenerExecution execution) {   
  4.     System.out.println("leaving "+execution.getEventSource());   
  5.   }   
  6. }  

注意事件監(jiān)聽器的目的不是可視化,這是為什么事件監(jiān)聽器本身 不應(yīng)該顯示在圖形中。一個(gè)DisplaySource事件監(jiān)聽器 會(huì)作為end事件的監(jiān)聽器添加到組合活動(dòng)中。

下一個(gè)流程展示了DisplaySource事件監(jiān)聽器如何 作為'end'事件的監(jiān)聽器注冊到composite活動(dòng):
一個(gè)在組合活動(dòng)中為end事件注冊了不可見的事件監(jiān)聽器的流程。

一個(gè)在組合活動(dòng)中為end事件注冊了不可見的事件監(jiān)聽器的流程 

圖 5.8. 一個(gè)在組合活動(dòng)中為end事件注冊了不可見的事件監(jiān)聽器的流程。

TODO 更新代碼片段

下一步,我們會(huì)啟動(dòng)一個(gè)執(zhí)行。

ClientExecution execution = processDefinition.startProcessInstance();

在啟動(dòng)一個(gè)新執(zhí)行后,執(zhí)行將在a活動(dòng)中 作為初始活動(dòng)。沒有活動(dòng)離開,所以沒有信息被記錄下來。 下一個(gè)signal會(huì)給與執(zhí)行, 導(dǎo)致它選擇從a到b。

execution.signal();

當(dāng)signal方法返回,執(zhí)行會(huì)選擇轉(zhuǎn)移 然后end事件會(huì)被a活動(dòng)觸發(fā)。 那個(gè)組合活動(dòng)會(huì)被傳播到組合活動(dòng)和流程定義中。 因?yàn)槲覀兊腄isplaySource 監(jiān)聽器放到 composite活動(dòng)中, 它會(huì)接收事件,把下面的信息打印到控制臺(tái)中:

leaving activity(a)

另一個(gè)

execution.signal();

會(huì)選擇b到c的轉(zhuǎn)移。那會(huì)觸發(fā)兩個(gè)活動(dòng)離開事件。 一個(gè)在b活動(dòng),一個(gè)在組合活動(dòng)。 所以下面的幾行會(huì)添加到控制臺(tái)輸出中:

leaving activity(b)
leaving activity(composite)

事件傳播建立在流程定義的繼承組合結(jié)構(gòu)中。 ***元素總是流程定義。 流程定義包含一系列活動(dòng)。每個(gè)活動(dòng)可以是葉子活動(dòng)或者可以是一個(gè)組合節(jié)點(diǎn), 這意味著它包含了一系列內(nèi)嵌活動(dòng)。 內(nèi)嵌活動(dòng)可以被使用,比如超級狀態(tài)或組合活動(dòng),在內(nèi)嵌流程語言中,像BPEL。

所以事件模型在組合活動(dòng)和上面的流程定義中的功能是相似的。 想象'Phase one'模型一個(gè)超級狀態(tài)作為一個(gè)狀態(tài)機(jī)。 然后事件傳播允許在超級狀態(tài)中注冊所有事件。 這個(gè)主意是繼承組合響應(yīng)圖形展示。 如果一個(gè)'e'元素畫在另一個(gè)'p'元素中, 'p'是'e'的父節(jié)點(diǎn)。一個(gè)流程定義擁有一系列定義活動(dòng)。 每個(gè)活動(dòng)可以擁有一系列內(nèi)嵌活動(dòng)。 一個(gè)轉(zhuǎn)移的父節(jié)點(diǎn)就是它的源頭和目的的***個(gè)父節(jié)點(diǎn)。

如果一個(gè)事件監(jiān)聽器對傳播的事件沒有興趣, 可以在構(gòu)建流程使用ProcessFactory的propagationDisabled()。 下一個(gè)流程是與上面相同的流程, 除了傳播的事件會(huì)被事件監(jiān)聽器禁用。 圖形還是一樣。
注冊到'end'事件的事件監(jiān)聽器被禁用的流程。

注冊到end事件的事件監(jiān)聽器被禁用的流程 

圖 5.9. 注冊到'end'事件的事件監(jiān)聽器被禁用的流程。

使用流程工廠構(gòu)建流程:

TODO 更新代碼

所以當(dāng)***個(gè)signal在流程中調(diào)用時(shí),end事件 會(huì)再次觸發(fā)在a活動(dòng)上,但是現(xiàn)在在組合活動(dòng)的事件監(jiān)聽器 不會(huì)被執(zhí)行,因?yàn)閭鞑サ氖录唤昧恕?禁用傳播是單獨(dú)的事件監(jiān)聽器的一個(gè)屬性, 不會(huì)影響其他監(jiān)聽器。事件會(huì)一直被觸發(fā), 傳播到整個(gè)父繼承結(jié)構(gòu)。

ClientExecution execution = processDefinition.startProcessInstance();

***個(gè)signal會(huì)選擇從a到b的流程。 沒有信息會(huì)被打印到控制臺(tái)。

execution.signal();

下一步,第二個(gè)signal會(huì)選擇從b到c的轉(zhuǎn)移。

execution.signal()

還是兩個(gè)end事件被觸發(fā), 就像上面分別在b和composite活動(dòng)中。 ***個(gè)事件是b活動(dòng)上的 end事件。 那將被傳播給composite活動(dòng)。 所以事件監(jiān)聽器不會(huì)為這個(gè)事件執(zhí)行,因?yàn)樗呀?jīng)禁用了傳播。 但是事件監(jiān)聽器會(huì)在composite活動(dòng)上 為end事件執(zhí)行。 那是不傳播的,但是直接在composite活動(dòng)上觸發(fā)。 所以事件監(jiān)聽器現(xiàn)在會(huì)被執(zhí)行 一次,為組合活動(dòng),就像下面控制臺(tái)里顯示的那樣:

leaving activity(composite)

【編輯推薦】

  1. jBPM4實(shí)現(xiàn)基本活動(dòng)(上)
  2. jBPM與Spring整合淺析
  3. jBPM 4.0配置淺析
  4. jBPM4的架構(gòu)
  5. 淺談jBPM下MySQL的配置
責(zé)任編輯:yangsai 來源: BlogJava
相關(guān)推薦

2009-06-26 09:15:31

jBPM4基本活動(dòng)

2009-06-24 14:57:03

jBPM4架構(gòu)

2009-06-26 13:51:49

jBPM4高級圖形執(zhí)行

2009-06-29 14:42:54

2009-06-23 15:30:20

jBPMMySQL

2010-01-20 09:23:38

jBPM高級交互模式jBPM四眼原則

2019-09-19 11:52:59

Linux腳本語言Vim

2022-04-25 16:27:33

春節(jié)活動(dòng)紅包除夕

2010-05-12 16:13:04

2009-06-24 16:23:29

jBPM 4.0配置

2018-06-22 15:25:31

LinuxDocker容器管理

2009-06-11 13:53:35

jBPM用戶指南

2009-06-25 17:13:51

jBPM與Spring

2010-05-14 09:57:25

MySQL數(shù)據(jù)庫

2009-06-23 15:49:00

Liferay Por

2021-11-19 14:33:27

挖礦木馬病毒

2014-07-31 13:41:36

程序員

2019-12-03 18:31:55

聯(lián)通/云時(shí)代/創(chuàng)新

2009-06-11 14:00:34

jBPM用戶指南jBPM范例

2009-06-11 13:43:21

jBPM用戶指南jBPM 4.0
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號