Activiti工作流學習-----基於5.19.0版本(7)

来源:http://www.cnblogs.com/liujie037/archive/2016/08/25/5799905.html
-Advertisement-
Play Games

八、BPMN 2.0流程圖詳解 BPMN 2.0的標準的出現是好事,用戶不在被某個工作流開發商綁架或者在工作流中開發妥協,Activiti作為BPMN標準的一套解決方案,使得用戶在選擇工作流框架時可以平滑的遷移過渡。也有負面的不好的消息,就是BPMN標準是大量開會討論和開發商妥協的結果(一般這是在做 ...


八、BPMN 2.0流程圖詳解

BPMN 2.0的標準的出現是好事,用戶不在被某個工作流開發商綁架或者在工作流中開發妥協,Activiti作為BPMN標準的一套解決方案,使得用戶在選擇工作流框架時可以平滑的遷移過渡。也有負面的不好的消息,就是BPMN標準是大量開會討論和開發商妥協的結果(一般這是在做夢),所以用戶在閱讀BPMN規範會感覺到它太笨重了,Activiti開發工作流將用戶體驗放到第一位置,開發出了工作流設計插件。工作流官方推薦使用工作流設計插件。

8.1 事件(Event)

每個流程設計都有start event和end event,而在整個流程中發生的事件都是有event來表示。事件在設計面板中用圓圈表示,在BPMN 2.0中主要有兩種事件:

  • Catching:當流程執行到事件的時候, 它會等待被觸發。而觸發條件需要用戶配置在這個圓圈圖標的屬性裡面,和下麵第二種圓圈圖標外形上的區別是:Catching圖標裡面是空的,就是空圈。
  • Throwing:當流程執行到事件的時候,它會立即觸發,同樣的觸發器也需要配置在圖標屬性裡面,和Catching圖標不同是圓圈圖標裡面有東西是,黑色的。

總的來說,事件定義決定了事件的語義。如果沒有事件定義,這個事件就不做什麼特別的事情。 沒有設置事件定義的開始事件不會在啟動流程時做任何事情。如果給開始事件添加了一個事件定義 (比如定時器事件定義)我們就聲明瞭開始流程的事件 "類型 " (這時定時器事件監聽器會在某個時間被觸發)。

8.1.1 定時器事件

  定時器事件是根據指定的時間觸發的事件。可以用於開始事件(start event), 中間事件(intermediate event)和邊界事件(boundary event)。定時器事件必須含有下麵一種屬性的配置。

timeDate:指定ISO 8601格式的日期定時器激活。(至於ISO 8601日期格式可以詳見百度:http://baike.baidu.com/view/931641.htm)

<timerEventDefinition>
    <timeDate>2016-08-23T18:13:00</timeDate>
</timerEventDefinition>

timeDuration:定義定時器經過多少時間後激活。時間段也是取得ISO 8601格式,比如在一年三個月五天六小時七分三十秒內,可以寫成P1Y3M5DT6H7M30S。

<timerEventDefinition>
    <timeDuration>P10D</timeDuration>
</timerEventDefinition>

timeCycle:定義定時器重覆間隔,在某些場景使用,比如周期性的啟動流程,任務超時發送提醒。timeCycle的設置目前有兩種方式:ISO 8601和Cron表達式(quartz任務調度框架提供的解決方案),activiti預設是使用ISO 8601。例如現在重覆三次,每次間隔10小時:

1 <timerEventDefinition>
2     <timeCycle activiti:endDate="2016-08-22T16:42:11+00:00">R3/PT10H</timeCycle>
3 </timerEventDefinition>
<timerEventDefinition>
    <timeCycle>R3/PT10H/${EndDate}</timeCycle>
</timerEventDefinition>

其中endDate是可選的配置,上面使用了兩張方式加上了endDate, 定時器將會在指定的時間停止工作。

此外如果你使用Cron 表達式,可以這樣寫:

0 0/5 * * * ?

註意: 第一個數字表示秒,而不是像通常Unix cron中那樣表示分鐘。重覆的時間周期能更好的處理相對時間,它可以計算一些特定的時間點 (比如用戶任務的開始時間),而cron表達式可以處理絕對時間, 這對定時啟動事件特別有用。

你可以使用表達式進行配置,在裡面動態設置值,不過該值需要為ISO 8601或者(cron表達式)格式,

<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport">
  <timerEventDefinition>
    <timeDuration>${duration}</timeDuration>
  </timerEventDefinition>
</boundaryEvent>

定義器的執行有先決條件:async executor和job被啟用定時器才會激活(例如在activiti.cfg.xml中配置了jobExecutorActivate或者asyncExecutorActivate為true)。

8.1.2 錯誤事件定時器

BPMN的錯誤是關於業務上面的異常處理,它和java代碼上的異常是不同的,兩者完全不同,比如這樣配置一個錯誤事件:

1 <endEvent id="myErrorEndEvent">
2   <errorEventDefinition errorRef="myError" />
3 </endEvent>

 8.1.3 信號事件

信號事件會引用一個命名的信號,所謂的信號作用在整個流程引擎全局範圍內,會發送給所有活躍的處理器。信號事件在BPMN文件中是定義在signalEventDefinition中,其中的signalRef屬性可以引用前面聲明的signal,而signal在definitions的根節點中作為子元素,下麵就是一個例子

 1 <definitions... >
 2     <!-- 聲明signal -->
 3     <signal id="alertSignal" name="alert" />
 4 
 5     <process id="catchSignal">
 6         <intermediateThrowEvent id="throwSignalEvent" name="Alert">
 7             <!-- signal event definition -->
 8             <signalEventDefinition signalRef="alertSignal" />
 9         </intermediateThrowEvent>
10         ...
11         <intermediateCatchEvent id="catchSignalEvent" name="On Alert">
12             <!-- signal event definition -->
13             <signalEventDefinition signalRef="alertSignal" />
14         </intermediateCatchEvent>
15         ...
16     </process>
17 </definitions>

Throwing信號事件:在BPMN中配置或者用代碼實現都可以發出信號,而使用代碼可以這樣子:

1 RuntimeService.signalEventReceived(String signalName);
2 RuntimeService.signalEventReceived(String signalName, String executionId);

這兩個方法不同之處在於第一個方法發出全局的信號,第二個方法會指定execution發出信號。

Catching信號事件:被中間事件和邊界事件捕獲的事件。

前面第二個方法的executionId或者查詢當前活躍的信號事件方法如下:

1 List<Execution> executions = runtimeService.createExecutionQuery()
2       .signalEventSubscriptionName("alert")
3       .list();

信號的作用範圍:

 預設的信號作用域是整個流程引擎,也就是說你可以throw一個信號在多個流程實例之間併發生作用。有時候我們需要作用範圍僅僅是在發生事件的流程實例里,限制信號的作用範圍,可以這樣配置,不過它並不是BPMN2.0規範中的,是activiti獨有的,其中activiti:scope的預設值是global。

1 <signal id="alertSignal" name="alert" activiti:scope="processInstance"/>

信號事件案例:這裡我使用了Activiti Explorer線上流程圖設計器設計了兩張圖,展示了信號交互。

第一張流程是從保險規則變動開始的,然後相關人員審批,如果同意後會發出保險條件發生改變的信號。

第二張流程中將在紅框標識的地方會捕獲(Catching)這個事件,使得保險合同在這時重新計算。

信號是通過廣播傳遞給所有活躍的事件,但有時候我們並不是想要這種結果,譬如下圖:

上面流程圖的意思是執行“do something”任務時出現的錯誤,會被邊界錯誤事件捕獲, 然後使用信號傳播給併發路徑上的分支,進而中斷"do something inparallel"任務, 但是,根據信號的廣播含義,它也會傳播給所有其他訂閱了信號事件的流程實例,這就是我們不想要的。這時我們需要調用前面介紹觸發信號的API的第二個方法進行手動關聯。

8.1.4 消息事件

消息事件會引用已命名的消息。和信號不同的是,消息具有名稱和內容,並且消息始終指定了單個的接收者。 

消息事件定義在BPMN文件的messageEventDefinition元素中,其中messageRef屬性值來自於message,至於message是配置在definitions的根元素裡面。下麵是一個例子:

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

  <message id="newInvoice" name="newInvoiceMessage" />
  <message id="payment" name="paymentMessage" />

  <process id="invoiceProcess">

    <startEvent id="messageStart" >
        <messageEventDefinition messageRef="newInvoice" />
    </startEvent>
    ...
    <intermediateCatchEvent id="paymentEvt" >
        <messageEventDefinition messageRef="payment" />
    </intermediateCatchEvent>
    ...
  </process>

</definitions>

 拋出消息事件:Activiti作為嵌入式的引擎,它不會關註怎麼接收消息,接收消息取決於你的環境和特定的平臺,比如你可以連接到JMS消息隊列或者執行WebService或REST請求,這是需要你的應用層架構中進行實現,Activiti只是其中一部分。

在你的應用裡面收到消息,你需要處理它,如果是啟動流程實例的消息,可以參考下麵的API:

1 ProcessInstance startProcessInstanceByMessage(String messageName);
2 ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
3 ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);

這些API允許使用引用的消息進行啟動流程實例。如果流程實例需要接收這些消息,首先你需要關聯指定流程實例和消息,然後觸發處於等待的流程,使用RunTimeService可以觸發基於消息的流程。

1 void messageEventReceived(String messageName, String executionId);
2 void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);

查詢訂閱消息事件的流程定義:

對於start event的消息,消息事件關聯到指定的流程定義,消息的訂閱可以使用ProcessDefinitionQuery查詢。

1 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
2       .messageEventSubscription("newCallCenterBooking")
3       .singleResult();

對於明確的消息是對應一個流程的,所以查詢結果一般是0個或者1個,如果是流程定義更新,那麼方法返回最新的流程定義。

如果是中間消息事件,訂閱的消息關聯到特定的流程,我們可以使用ExecutionQuery進行查詢:

1 Execution execution = runtimeService.createExecutionQuery()
2       .messageEventSubscriptionName("paymentReceived")
3       .variableValueEquals("orderId", message.getOrderId())
4       .singleResult();

下麵的實例通過兩個不同的消息進行啟動流程實例:

 在某些需要多個start event啟動流程實例需要統一的處理方式的時候是有用處的。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 學習記錄 O(∩_∩)O 、 如果你恰巧路過,希望你能停下腳步瞧一瞧,不足之處望指出,感激不盡~ 使用工具: 1、eclipse 2、hibernate壓縮包(hibernate_4.3.11) 3、mysql 準備工作: 創建工程——>導入hibernate.jar包——>編寫 hibernate ...
  • 寫在前面的話 最近一直在邊工作邊學習分散式的東西,看到了構建Java中間件的基礎知識,裡面有提到Java多線程併發的工具類,例如ReentrantLock、CyclicBarrier、CountDownLatch... 以前在工作中也有用到過這些實用的工具類,但是瞭解不是特別深入,藉此機會打個卡,好 ...
  • Web框架本質 眾所周知,對於所有的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。 上述通過socket來實現了其本質,而對於真實開發中的python web程式來說,一般會分為兩部分:伺服器程式和應用程式。伺服器程式負責對socket伺服器進行封裝, ...
  • 每一項技術用的人多了,就會有人將其進行優化,做成一個簡單、實用、大眾化的工具,這對於初識者來說是非常方便的,但是對於長久學習或工作這方面的人技術人員來說是不可取的,所以還是要學習基礎的實用方法。因此,我就在ubuntu下配置了Apache伺服器來更深入的學習。 這是一個預設安裝的方法,如果要指定 步 ...
  • 解決的問題 HBase的Write Ahead Log (WAL)提供了一種高併發、持久化的日誌保存與回放機制。每一個業務數據的寫入操作(PUT / DELETE)執行前,都會記賬在WAL中。 如果出現HBase伺服器宕機,則可以從WAL中回放執行之前沒有完成的操作。 本文主要探討HBase的WAL ...
  • 由於網站項目需要上傳和下載資源,資源大小有幾M到幾百M不等,傳輸的效率暫不考慮,所以先搭建FTP伺服器供項目使用。 下載Filezilla Server後安裝,沒特殊要求,下一步直至結束。 安裝完成後打開程式居然報錯: 錯誤提示有2個,第一個需要設置被動模式的路由,【Edit】->【Setting】 ...
  • 新建對話框應用程式,刪除自動生成的控制項後,拖拽一個CListCtrl控制項,綁定變數名為:m_listctrl。在對話框初始化成員函數OnInitDialog()中鍵入以下代碼即可實現自適應系統的CListCtrl控制項! 下麵是這兩種樣式的對比圖: ...
  • 這裡想說一下在集合框架前需要理解的小知識點,也是個人的膚淺理解,不知道理解的正不正確,請大家多多指教。這裡必須談一下java的泛型,因為它們聯繫緊密,我們先看一下這幾行代碼: 這裡主要想測試一下這兩個類是不是相等的,根據我之前的認識,這應該是不相等的,但是運行輸出的結果是: class java.u ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...