.NET 開源工作流: Slickflow流程引擎基礎介紹(二) -- 引擎組件和業務系統的集成


  1. 集成流程引擎的必要性

    業務過程的變化是在BPM系統中常見的現象,企業管理層需要不斷優化組織架構,改造業務流程,不可避免地帶來了業務流程的變化,企業信息系統就會隨之面臨重構的可能性。一種直接的方式是改造業務代碼,適應業務過程的變化,這將會面臨不斷改寫代碼的需求;還有一種方式是使用流程引擎控制業務過程的變化,將改寫業務代碼的操作交由流程引擎,通過流程引擎解析業務規則,驅動業務過程流轉,從而將改寫業務代碼的可能性降到最低。

    顯而易見,流程引擎帶來的好處是為了更好解決業務過程變化后帶來的重構風險,信息系統如果是柔性的,可伸縮,可動態適應的,那么它才可以保持不被很快被替代的可能性,自然就能夠為企業降低不斷升級或實施產生的成本費用。

  2. 業務系統和流程引擎的交互方式

    業務系統中嵌入流程引擎中間件,是一種常見而直接的方式;雖然有些引擎組件能夠配置業務模塊的反射接口,但是我們目前認為比較合理的方式是:流程引擎不應過多地綁定業務接口,因為業務接口的變化是始終不可避免,會一直發生的,而引擎組件同樣需要保持穩定。

    通常在業務模塊中,當處理業務功能后,也會調用引擎組件的服務接口,驅動業務流程流轉。我們一直把業務變化部分交由業務過程的服務處理,流程引擎中間件始終只處理解析規則,驅動流轉的職責。這樣可以避免引擎組件的功能膨脹,保持引擎組件的靈巧。

    常見的業務過程調用流程引擎服務接口的圖示:

    Step 1:  當前正在執行功能單元發起的調用

    Step 2:  執行完畢,下一步已經處在等待中的功能單元

  3. 流程引擎中間件集成方式的優勢

    首先,流程引擎中間件的職責是解析業務規則,驅動業務過程運轉。人們不斷地將引擎功能封裝為組件,從而方便業務模塊的調用。將最復雜,最容易變化的部分交由引擎中間件處理,才可以讓用戶更加專注於業務功能的實現。將引擎組件的功能從業務模塊中分離出來,整體上降低了整個系統的復雜程度,使業務系統變得更加容易維護。

    其次,流程引擎中間件提供動態組件引用,以及WebService訪問;可以滿足多種架構系統的集成需求。在當前互聯網雲端模式的軟件架構盛行的模式下,中間件可以以WebService方式提供Restful的API接口,使得引擎提供的服務能夠跨越系統結構,組織邊界來驅動業務過程流轉,這種分布式的模式極大地發揮了引擎中間件的功能效用。

  4. 代碼示例

    以下代碼演示業務類(生產訂單)如何集成工作流引擎並調用服務接口的過程。

  4.1 實現IWfServiceRegister接口

    /// <summary>
    /// 工作流注冊接口
    /// </summary>
    public interface IWfServiceRegister
    {
        WfAppRunner WfAppRunner { get; set; }
        void RegisterWfAppRunner(WfAppRunner runner);
    }

  4.2 接口實現代碼示例

    /// <summary>
    /// 生產訂單服務
    /// 示例代碼,請勿直接作為生產項目代碼使用。
    /// </summary>
    public partial class ProductOrderService : ServiceBase, IProductOrderService, IWfServiceRegister
    {
        #region IWorkflowRegister members
        public WfAppRunner WfAppRunner
        {
            get;
            set;
        }
        public void RegisterWfAppRunner(WfAppRunner runner)
        {
            WfAppRunner = runner;
        }
        #endregion
    }

  4.3 業務調用示例

  1) WfService服務接口注冊

    IWfServiceRegister sr = ProductOrderService as IWfServiceRegister;
    sr.RegisterWfAppRunner(runner);
    WfAppResult appResult = ProductOrderService.Sample(productOrder);     //此處調用業務類的節點方法,內部有流程交互代碼。
    if (appResult.Status == 1)
        result = ResponseResult.Success("打樣操作成功!");
    else
        result = ResponseResult.Error(string.Format("打樣操作失敗:{0}", appResult.Message));

  2) 業務類方法實現

    /// <summary>
    /// 打樣
    /// </summary>
    /// <param name="entity"></param>
    public WfAppResult Sample(ProductOrderEntity entity)
    {
        var appResult = WfAppResult.Default();
        var wfas = new WfAppInteropService();
        var session = SessionFactory.CreateSession();
        try
        {
            session.BeginTrans();
            //流程運行
            var result = wfas.RunProcess(session, WfAppRunner, WfAppRunner.Conditions);    //流程交互類調用
            if (result.Status == WfExecutedStatus.Success)
            {
                //寫步驟記錄表
                Write(session, WfAppRunner, "打樣", entity.ID.ToString(), entity.OrderCode, "完成打樣");
                //業務數據處理部分,此處是簡單示例...
                UpdateStatus(entity.ID, (short)ProductOrderStatusEnum.Sampled, session);
                session.Commit();
                appResult = WfAppResult.Success();
            }
            else
            {
                session.Rollback();
                appResult = WfAppResult.Error(result.Message);
            }
        }
        catch (System.Exception ex)
        {
            session.Rollback();
            appResult = WfAppResult.Error(ex.Message);
        }
        finally
        {
            session.Dispose();
        }
        return appResult;
    }

  4.4 流程應用交互API封裝

    /// <summary>
    /// 工作流運行
    /// </summary>
    /// <param name="session"></param>
    /// <param name="runner"></param>
    /// <returns></returns>
    public WfExecutedResult RunProcess(IDbSession session, WfAppRunner runner, IDictionary<string, string> conditions = null)
    {
        var result = new WfExecutedResult();
        var wfService = new WorkflowService();
        var nodeViewList = wfService.GetNextActivityTree(runner, conditions).ToList<NodeView>();
        foreach (var node in nodeViewList)
        {
            var performerList = wfService.GetPerformerList(node);       //根據節點角色定義,讀取執行者列表
            Dictionary<string, PerformerList> dict = new Dictionary<string, PerformerList>();
            dict.Add(node.ActivityGUID, performerList);
            runner.NextActivityPerformers = dict;
            if (node.IsSkipTo == true)        //特定節點上的判斷處理
            {
                result = wfService.JumpProcess(session.Connection, runner, session.Transaction);
            }
            else
            {
                result = wfService.RunProcessApp(session.Connection, runner, session.Transaction);
            }
        }
        return result;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM