業務流程引擎


一般的時候,我們都采用編程式開發,編程式開發的好處非常明顯:直接、高效、自由,當然其缺點也是有的,與其優點剛好相對,因為直接,所以有些變化都要進行代碼上的修改;因為高效,所以一旦出問題,導致的結果也比較嚴重,因為自由,所以帶來的修改風險也比較大。  這也就是許多大的公司都在進行流程化開發的重要原因之一,比如:上海普元,Livebos, Justep,還有許許多多知名不知名的公司都有類似的流程化開發引擎存在,通過流程化開發,增強代碼的復用性,降低軟件開發成本及測試成本,提升軟件的可維護性及降低維護成本。 
Tiny框架在這方面也有自己的方案,Tiny主要考慮幾個方面的問題: 
a.組件擴充的便捷性 
組件的擴充的便捷性是指,流程其實玩的就是組件,如果組件擴充起來非常困難,會直接影響到流程引擎的可用性。所以Tiny框架的流程引擎的組件結構非常之簡單,僅有一個接口方法;流程組件的注冊與加載也是非常重要的,如果在擴充流程組件的時候,需要復雜的注冊或配置過程,這個時候流程擴充的便捷性也會大大降低。Tiny框架采用了引用即注冊的方案,只要把流程組件放入系統運行環境之間,就完成了流程組件的注冊,即可以在流程中使用,便得流程組件的擴充的便捷性大大提高。 
b.流程的面向對象特性支持  流程的面向特性支持是指在Tiny框架中流程是具有面向對象的特性的。流程可以進行繼承,這樣帶來一個好處就是多個流程中重復的部分,可以定義在一個父流程中,然后子流程只要繼承父流程,即可;流程節點是可以被覆蓋的,也就是說,在父流程中可以定義一個空節點,但是流程中定義了流轉關系,但是流程節點的實現留在子流程中實現; 
c.流程的易編輯性 
流程的編輯必須方便、容易,有專門的流程編輯工具更好,沒有的時候,使用普通的Xml編輯器也可以方便的進行編輯。 
d.流程的可重入性 
一般的流程引擎都是不可重入的,也就是只能從開始執行,執行到結束結點之后完成。Tiny流程引擎支持流程重入,也就是說,不一定是從開始結點執行,可以從任意一個結點執行。這個機制為程序的邏輯提供了非常大的自由度,可以利用此特性容易的構建頁面流引擎或工作流引擎。即使是業務流程引擎,也會由此獲得更大的自由度。 
由於支持流程的可重入性,在本流程處理當中,不僅可以在當前流程中進行切換與轉接,還可以流轉到其他流程的節點當中,這在業務處理及頁面處理,流程處理方面都提供了極大的使得,但是這也是一個雙刃劍,在提供了這么靈活的功能的同時,也會導致業務流程看起來比較復雜,因此,控制方面最好由架構師或核心開發人員來編寫,普通開發人員只開發具體的業務點即可。 
呵呵,說了這么多,大家理解起來可能還是比較抽象,那就來個例子看看: 

1
2
3
4
5
6
7
8
9
10
11
<flow id="1000" name="Hello">
    <nodes>
          <node id="begin">
                <component class-name="org.tinygroup.flow.HelloWorldComponent">
                    <properties>
                        <property name="name" value="world" />
                    </properties>
                </component>
          </node>
    </nodes>
< /flow>



HelloWorldComponent的源碼如下: 

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorldComponent implements ComponentInterface {
    String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void execute(Context context) {
        context.put("result", String.format("Hello, %s", name));
    }
}



可以看出,所有組件必須實現ComponentInterface 接口 
從其實現邏輯可以看出,它就是把“Hello, ”加上輸入的名字,放在了環境變量的result當中。
 下面看看執行結果: 
a.按默認開始結點開始執行 

1
2
3
Context context = new ContextImpl();
flowExecutor.execute("1000",  context);
assertEquals("Hello, world", context.get("result"));



b.從指定節點開始執行 

1
2
3
Context context = new ContextImpl();
flowExecutor.execute("1000","begin", context);
assertEquals("Hello, world", context.get("result"));



可以看到確實是執行並返回了結果,但是它的執行機理是怎么樣的呢?? 
實際上,上面的流程是一個簡化的流程,就是說Tiny流程引擎的有些參數不輸入,也可以按照約定正確的執行,實際上寫得完整的話,例子是下面這個樣子的:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<flow id="1000" version="1.0" privateContext="false" extend-flow-id="" name="Hello" title="你好示例" default-node-id="end" begin-node-id="begin" end-node-id="end" enable="true">
  <description>some thing....</description>
  <nodes>
    <node id="begin">
      <component class-name="org.tinygroup.flow.HelloWorldComponent">
        <properties>
          <property name="name" value="world"/> <span></span> </properties>
      </component>
      <next-nodes>
        <next-node exception-type="java.lang.Exception" next-node-id="end"/>
      </next-nodes>
    </node>
  </nodes>
< /flow>



其中flow節點的屬性含義為:
id,唯一確定一個流程
privateContext,如果是true,則在流程單獨申請一個context,否則共用調用者的context,這樣可以有效避免環境變量沖突問題
extend-flow-id,繼承的流程id,這個繼承id是一個非常強大的功能,后面詳細介紹
version版本號,同一id的流程可以存在多個版本,訪問時,如果不指定版本則默認采用最新版本
name,title僅用於說明其英文,中文名稱,易於理解而已。
default-node-id表示,默認執行節點,即如果一個組件執行完畢,其項值沒有指定下一處理節點則執行默認節點
begin-node-id,開始節點
end-node-id,結束節點
如果不指定,則begin-node-id默認為begin,end-node-id默認為end

node節點:id必須指定,在一個流程當中id必須唯一。
component節點
class-name用於指定組織實現類名
properties是組件的屬性列表
property中的name與value是組件的屬性的值,value,這里傳入的是個字符串,但是實際當中可以處理中可以非常靈活,后面再介紹。
next-nodes,是指根據執行結果進行后續處理的規則。 
next-node,具體的一條規則,component-result,匹配項,支持正則表達式,節點中的組件執行結果進行匹配,匹配成功則執行此規則中的下一節點。
exception-type是異常的類名稱,如果出現異常且與這里定義的類型匹配,則執行此規則中的下一節點。 
上面說到繼承,流程繼承實現起來是非常簡單的,只要在extend-flow-id屬性中指定即可。
繼承不支持多繼承,即流程只能繼承自一個流程,但是可以支持多層繼承,即
a>b>c>d.....
實際開發過程中,不要把繼承搞得太復雜,這樣會把程序邏輯搞得更難理解的。


繼承實際會起到什么作用呢?
首先,會繼承一些屬性,另外會把節點信息繼承過來。
簡單來說就是:兩者都有,當前流程說了算,當前沒有,父流程說了算。


繼承應用到什么場景呢??
繼承應用於業務處理的模式非常相似,只有中間處理環境不同的時候。
比如:
A  B  C  D ---O--- -D -C -B -A
類型的業務處理流程,只有O不同,其他處理模式完全相同,此時采用繼承方式都非常舒服了,
只要定義父流程,在子流程中只用定義O一個流程節點即可。以后要統一進行流程調整,只要在父流程中進行調整就可以了。

比如:flow aa定義為 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<flow id="aa" name="aa">
  <nodes>
    <node id="begin">
      <next-nodes>
        <next-node component-result="begin" next-node-id="hello"/>
      </next-nodes>
    </node>
    <node id="hello">
      <component class-name="org.tinygroup.flow.HelloWorldComponent">
        <properties>
          <property name="name" value="world"/>
        </properties>
      </component>
      <next-nodes>
        <next-node next-node-id="end"/>
      </next-nodes>
    </node>
  </nodes>
< /flow>



flow bb定義為 

1
2
3
4
5
6
7
8
9
10
11
<flow id="bb" name="bb" extend-flow-id="aa">
< nodes>
< node id="hello">
< component class-name="org.tinygroup.flow.HelloWorldComponent">
< properties>
< property name="name" value="world" />
< /properties>
< /component>
< /node>
< /nodes>
< /flow>





則流程bb也可以順利執行,且執行結果是Hello, world  


非常重要的一個亮點就是屬性賦值。  
屬性賦值是否好用,決定了框架的易用性。  


可以支持常量賦值"1"表示數字常量  
aa 表示字符串常量可以支持,環境變量賦值  
比如:xx表示從環境變量取xx鍵值的對象  
可以支持屬性賦值  
比如:xx.abc表示取環境變量xx的屬性abc  
比如:xx.abc.def表示取環境變量xx的屬性abc的屬性def  
可以支持組合賦值  

比如:${in:aa.abc.def}-${in:bb.cc.dd}    
表示把環境aa中的屬性abc的屬性def中間加"-"再加上環境變量bb中的cc的屬性的dd屬性  
其中屬性的層次不受限制。  


另外,取值方式,也支持自行擴展:  
比如:可以用${in:xmlkey.aa}也取在環境中xmlkey對應的xml節點的aa屬性  
所以,只有想不到的,沒有做不到的。   

應用開發與部署方式,比較典型的有B/S與B/A/S,C/A/S等。對於B/A/S和C/A/S方式,因為A與B和C是分離部署的,所以,所有的內容都需要是通過Context進行傳遞的。  

如果是通過分離式部署,那么就需要通過網絡來傳遞請求環境數據。  

如果是想通過B/S環境來構建系統,此時就會期望通過HTTP處理線程來同布調用流程處理結果。  
同時,有時流程處理的數據可能是在Request,RequestAttribute,Session,Cookie中,如果把這些數據COPY到環境當中去,其實是有較大的性能消耗的。  

本流程引擎即支持通過服務方式調用,也可以通過短路方式進行調用。  
雖然我們推薦使用B/A/S體系架構,但是不能否認,目前我們的許多產品還是在B/S架構下運行的。  

但是好在,這個對於流程引擎來說,他並不直接訪問Request和Session,Cookie等內容,所以,即使是集成在一起部署,也不妨礙進行分離式部署,依然可以保證服務的無狀態特性,前提就是需要實現一個Context的接口。  
小結: 
Tiny的流程引擎,提供了相當強悍的功能及擴展性,上面只說了一部分,有些也沒有完全說清楚,實際上,還提供了包含EL表達式等許多高級功能,對於期望進行流程式編排開發來說,有相當好的支持。 
目前在Tiny框架中,業務流程編排及頁面流程編排都是基於此引擎構建,應用效果非常良好。未來會基於其構建工作流引擎。


免責聲明!

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



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