前言:流程實現基本流轉功能外,通常也需要調用外部事件,用於和業務系統的交互,同時存儲一些流程變數,用於追蹤和記錄業務數據變化對流程流轉的影響。 1. 流程事件 流程執行過程中,伴隨各種事件的發生,而且是存在於整個流程的生命周期,即從流程啟動一直到流程結束的整個過程都有事件發生。這些事件的發生,業務系 ...
前言:流程實現基本流轉功能外,通常也需要調用外部事件,用於和業務系統的交互,同時存儲一些流程變數,用於追蹤和記錄業務數據變化對流程流轉的影響。
1. 流程事件
流程執行過程中,伴隨各種事件的發生,而且是存在於整個流程的生命周期,即從流程啟動一直到流程結束的整個過程都有事件發生。這些事件的發生,業務系統通常也需要知道一些流程過程的關鍵節點,或里程碑狀態。我們統稱為流程事件。
1.1 流程事件觸發類型
流程事件類型的定義是按照事件發生的位置來確定劃分,跟流程直接有關的比如有:啟動、運行、撤銷、退回、返送、跳轉、返簽和結束等。而跟活動有關的事件類型有:創建、執行和結束等。我們可以用下圖來描述常見的事件觸發:
1.2 流程事件觸發實現
流程事件的觸發,是按照先訂閱,後觸發的機制來實現。訂閱(Subscribe)是流程服務介面開放出來的方法,可以直接在這個方法裡面註冊匿名函數來綁定事件。程式代碼如下:
IWorkflowService wfService = new WorkflowService(); var wfResult = wfService.CreateRunner(runner.UserID, runner.UserName) .UseApp(runner.AppInstanceID, runner.AppName, runner.AppInstanceCode) .UseProcess(runner.ProcessGUID, runner.Version) .NextStep(runner.NextActivityPerformers) .IfCondition(runner.Conditions) //condition on the transiton .Subscribe(EventFireTypeEnum.OnActivityExecuting, (activityInstanceID, activityCode, delegateService) => { if (activityCode == "Task1") { delegateService.SetVariable("name", "book-task1"); delegateService.SetVariable("amount", "50"); } return true; }) .Run();
2. 事件類型節點
BPMN規範裡面,涉及到事件類型的節點,雖然不同於任務類型的節點,但是事件類型的節點通常都是表示一種流程的狀態,比如流程的開始和結束是最基本的兩個狀態。中間事件(Intermediate Event)是本次我們主要涉及到的事件類型的節點,其它事件類型的節點將在後期的文章中描述到。
2.1 中間事件(Intermediate Event)
中間事件(Intermediate Event)類型的節點一般用於流程中間狀態的變換,而且可以作為流程里程碑的事件或狀態觸發,用於通知業務系統流程的里程碑狀態已經發生,或者也可以收到業務系統的反饋的信息,用於一些流程下一步路徑的解析。
比如在中間事件觸發時,只有從業務系統中讀取到業務變數,然後傳入流程的下一步分支選擇條件變數中,才能確定下一步的流轉路徑。這樣的處理過程是經常的一種業務場景。一個有中間事件類型節點的流程圖示意如下:
2.2 節點上事件的定義
在流程設計器中,節點上的事件定義主要有兩個屬性:事件觸發的位置(執行前和執行後)、以及事件執行的表達式。一個定義示例描述如下:
觸發位置:執行前
表達式:Slickflow.Module.External.OrderSubmitService
2.3 業務服務的代碼實現
上文中提到的表達式是業務服務的程式代碼,業務服務的邏輯實現,除了本身的功能代碼實現,還需要繼承如下的兩個介面: ExternalServiceBase 和 IExternalService。 主要用於明確定義Execute()執行方法,然後在引擎內部執行過程中,在調用和執行這個介面方法。具體代碼示例如下:
/// <summary> /// 訂單提交服務類(對應訂單流程中訂單提交節點) /// </summary> public class OrderSubmitService : ExternalServiceBase, IExternalService { /// <summary> /// 業務邏輯前置調用方法 /// </summary> public override void Execute() { //實現用戶自己的業務邏輯 var id = DelegateService.GetID(); var amount = DelegateService.GetVariable("amount"); DoSomethingElse(amount, 20); } /// <summary> /// 業務邏輯具體實現方法 /// </summary> /// <param name="amount"></param> /// <param name="newAmount"></param> private void DoSomethingElse(string amount, int newAmount) { var intAmount = 0; int.TryParse(amount, out intAmount); if (intAmount < newAmount) { DelegateService.SetVariable("amount", newAmount.ToString()); } //調用其它業務處理邏輯 var session = DelegateService.GetSession(); //實現其它資料庫業務邏輯 //............................. } }
3. 委托服務的內部機制
委托服務用於統一處理所有流程發生的時間,跟事件交互過程中,除了觸發事件本身以外,還要考慮引擎內部和外部業務系統之間的交互。比如流程變數的保存和讀取就是一種交互應用。
3.1 委托服務介面
委托服務介面定義出事件訂閱時候的介面類型,具體代碼如下:
/// <summary> /// 委托介面 /// </summary> public interface IDelegateService { int ID { get; set; } int GetID(); IDbSession GetSession(); string GetVariable(string name, Nullable<ScopeTypeEnum> scopeType = null); void SetVariable(string name, string value, Nullable<ScopeTypeEnum> scopeType = null); string GetCondition(string name); void SetCondition(string name, string value); T GetInstance<T>(int id) where T : class; }
3.2 委托服務繼承類
繼承委托服務的介面實現目前有兩種類型,一是流程委托服務介面,而是活動委托服務介面。實現的主要目的是對流程變數的讀取和存儲,還有給外部應用展示流程實例的關鍵信息。
4. 流程變數
流程變數是流程流轉過程發生的一些數據變化,這些變數一般是來自業務系統的關鍵參數,而且在流程流轉時,通過條件表達式傳入,可以決定流程流轉下一步的路徑選擇。
4.1 流程變數類型
流程變數類型分為全局變數和局部變數。在程式中也可以命名為流程變數(ProcessVariable)和活動變數(ActivityVariable)。
4.2 流程變數存儲
流程變數的存儲是持久化存儲在資料庫表(WfProcessVariables)中,變數名和數值的key-value是其記錄格式。
delegateService.SetVariable("name", "book-task1"); delegateService.SetVariable("amount", "50");
5. 總結
流程引擎跟外部事件的交互實現,可以豐富業務過程的狀態變化和響應,通過流程變數的存儲,記錄業務過程中的關鍵數據變化,同時也做到了對流程分支選擇的路徑跟蹤。程式開發人員可以通過實現外部事件的委托服務,然後再訂閱流程過程事件,來徹底實現業務系統跟引擎內部的進一步協作整合。