摘要:計算機硬件需要中央處理器,而計算機軟件則需要中央控制器—工作流引擎。工作流引擎不但可以靈活控制軟件的業務邏輯,快速適應需求的變化,還可以大大提高軟件的開發效率,為公司節省成本提高競爭力。文章介紹了嵌入工作流引擎的設計思想與實現方法。
關鍵詞:工作流引擎;應用開發;Java;Hibemet;Servlet
0 引言
在每個軟件工程項目中,軟件工程師都會面對的一個問題是:邏輯,即遵循一定規律的流程。流程可能是業務流程,也可能是生產流程。軟件就是為這些流程量身定造的用于提高工作或生產效率的產物。因此在軟件的開發過程中,程序員都不斷地用重復的代碼去塑造出這些流程,即業內人士所述的工作流。然而,在軟件的維護過程中,往往由于業務或生產流程的變化,使得軟件必須作出相應的修改。于是開發人員又要面臨修改代碼的任務。簡單的流程代碼倒不成問題,若碰上比較復雜的流程,則需花上較長時間去弄清楚代碼的結構然后才能著手去修改,既費勁又容易出錯。于是,有人便提出把整個軟件流程圖形化地表現出來,而且可以自定義。工作流引擎便應運而生。工作流引擎不僅解決了軟件維護上的問題,而且它可以靈活地應用于不同的項目中,減少代碼的編寫量,從而加速軟件的開發過程。例如:業務流程A->B->C->B,用工作流引擎的方法表示如圖1所示。

顯然用工作流引擎的方法定義流程,既邏輯清晰又形象。倘若業務邏輯需要變化,只需在工作流引擎上把流程方向線修改一下便可,免除了改動代碼并且重新編譯程序的麻煩。越復雜的流程越能體現它的優點。
工作流引擎既然是為開發人員而設計的,當然是嵌入到軟件開發項目中的,它在整個軟件中起到了大腦的作用。幾乎所有相關的外圍程序都由它統一管理與觸發。例如圖1中的ExcuteA()就是我們所說的外圍程序。在實際開發的過程中,程序員只需編寫外圍程序然后把程序掛接到工作流引擎中適當的位置便可。就像工廠的生產線一樣,不同的階段做不同的加工。程序員只需管各階段怎么加工,而什么時候做什么加工就交給工作流引擎去做。
1 靈動的工作流引擎的設計思想
工作流引擎要求設計靈活,適應性強,才便于嵌入到各種項目中使用。圖2是一個輕量級工作流引擎設計方案,系統整體架構采用三層結構。

第一層是以Java Applet嵌入Web中實現的客戶端。該客戶端的優點在于不需安裝而實時下載到IE中使用,在應用開發中免去了由于平臺更新所帶來的客戶端重裝的麻煩。而且Java Applet在圖形界面方面的技術已經日趨成熟,利用Java中的AWT與Swing組件能較好地實現流程自定義界面的功能。當然優點的背后常常隱藏著缺點,這種做法必須以犧牲客戶端資源為代價。
第二層是以WebSphere為Web服務器的中間層。該層內部又分為兩層,上層是Java Servlet,下層是Hibemet。JavaServlet負責與客戶端的Applet通信;而Hibemet則負責Oracle數據庫的數據存取操作。兩者之間也進行著密切的數據交流,共同構建整個系統程序的主體。此處采用Hibemet作數據庫存取的中間件還有一個重要的優點就是Hibernet能靈活地支持多種數據庫類型,以持久化的思想代替數據庫存儲的思想。倘若在應用開發中的系統采用的不是Oracle數據庫,只需對Hibernet的設置作少量改動,工作流引擎便可兼容。
第三層是Oracle數據庫,負責高效的數據存取操作。
2 靈動的工作流引擎的實現
2.1 界面功能
界面布局分為四個區:功能按鍵區、樹型目錄區、流程元素區以及流程開發區,如圖3所示。
功能按鍵區:包括新建、保存、刪除以及退出等功能按鍵。樹型目錄區:其實就是把多個已存儲的流程按樹型結構顯示出來。流程元素區:包含開始節點、結束節點、普通節點以及方向線等流程中的元素。可把流程元素拖到流程開發區進行流程定義。流程開發區:進行流程定義的地方。在該區域可以自由地新建和拖動流程元素。
2.2 流程控制的實現
在數據庫中建立三個表,分別是:
(1)節點表:用于存儲流程中的節點屬性。包括名字、節點權限、在定義區的位置、所屬流程編號等。
(2)流向表:用于存儲流程的方向線。包括出發節點、指向節點、所屬流程編號、以及下面講述到的觸發函數和代謝函數。
(3)流程控制表:此表是流程控制的中心表。包括每個具體業務記錄的編號、當前所在節點編號(與節點表關聯)、所屬流程編號。每個新業務的辦理都必須先往該表插入一條新記錄。通過該表的信息可以查詢出當前用戶所屬節點有哪些待辦的業務。當用戶點擊按鈕把業務推向下一節點時,聯合流程控制表與流向表便可知道下一個節點是什么。只需在程序中把流程控制表中的“當前所在節點編號”字段修改為下一個節點編號,便可實現業務跟隨所定義的流程流轉從而到達流程控制的目的。
2.3 節點的權限
在圖3所示的流程處理中,需要提供一個對節點權限設置的功能,如圖4所示。
在每個節點的屬性中可以設置可讀寫用戶和只讀用戶權限。輸入框中填入應用系統的用戶登錄名用“,”隔開。在開發過程中用SQL查詢流程控制表和節點表便可得到當前登錄用戶在哪些節點,有哪些待辦任務,從而形成待辦業務列表提醒用戶辦理。
2.4 外圍程序調用
工作流引擎只承擔軟件中的大腦的作用,不實現任何的具體業務程序。為了實現工作流引擎對這些外圍的業務邏輯程序的調用,需要在節點屬性中添加兩個屬性觸發函數與代謝函數。
觸發函數是在用戶辦理業務時觸發的業務程序。例如觸發函數可以是一個彈出信息填寫界面的程序方法,在不同節點可以調用不同的觸發函數來實現該節點的業務辦理。代謝函數則在用戶辦理完該節點的業務后,點擊按鈕把業務推向下一節點時執行。它可以用于例如信息的補全或其他由程序自動完成的業務邏輯。
外圍程序的調用運用了Java中的接口實現方式。在工作流引擎中定義有觸發函數接口和代謝函數接口(類的其中一種)。接口中分別定義一個主方法mainFunction()。所有觸發函數類和代謝函數類分別實現這兩個接口。類的名稱填寫在節點屬性中的觸發函數和代謝函數輸入框,如圖5所示。
利用Java的反射機制,工作流引擎可以自動用所填寫的類名稱來實例化所對應的接口,然后統一調用主方法mainFunc-tion(),從而達到觸發該節點所對應的外圍業務程序的目的。代碼實現片斷如下:
觸發函數接口:
public interface TrigerFunctionInterface{
boolean mainFunction();
//定義主方法,用于觸發函數與代謝函數實現
}
觸發函數類:
public class BussinessLogic implements
TrigerFunctionInterface{
public boolean mainFunction(){
try{
…//業務邏輯代碼
return true;
}catch(Exception e){
e printStackTrace();
return 1;
}
}
}
工作流引擎中運用Java反射機制調用觸發函數類方式:
public class Trigger{
try {
//加載觸發函數類BussinessLogic
Class bussinessClass=Class.forName(“BussinessLogic”):
//實例化觸發函數類BussinessLogic
Object bussinessObject=bussinessClass.newlnstance();
Ctassl]classPara=new Class[1];
classPara[0]=String.classi
//加載主方法mainFunction
java lang.reflect.Method mainFunction=bussinessClass
.getMethod(“mainFunction”,1):
//調用主方法mainFunction
mainFunction.invoke(bussinessObject,1);
}catch(Exception e){
e printStackTrace():
}
}
2.5 并聯流程
有時候業務流程并不是單線而是并聯進行的。如圖3所示,業務同時經過部門B、部門c和部門D審批,他們之間沒有先后順序。此時流程控制表需要插入三條記錄分別對應于不同部門節點。所以為了兼容這并聯的案例,當業務被推向下一節點時,應該把流程控制表中的原記錄刪除,重新插入新記錄,而不只是像2.2所述的修改“當前所在節點編號”來實現。
經過三個部門同時審批后業務匯合到部門E。這里會出現兩種情況:一、需要經過三個部門的審批部門E才可辦理;二、只需經其中一個部門審批部門E便可辦理。為了實現這兩種需求,需要在節點中添加一個屬性“匯合”類型,可選值“與合”和“或合”。當選擇“與合”時,并聯的部門之間的關系便是“與”的關系,即實現情況一的需求。當選擇“或合”時,并聯的部門之間的關系便是“或”的關系,即實現情況二的需求。
2.6子流程
對于復雜的流程,由于節點太多。看起來錯綜復雜,所以把流程分為主流程和若干個子流程是很必要的。假設部門E在辦理時候也需要經部門內部幾個職員才能把業務辦理完。則需要在部門E的節點內定義子流程。子流程與主流程的隸屬關系可以在圖3中的樹型目錄區表現出來。
3 結束語
隨著國內軟件業的逢勃發展,競爭越來越激烈,誰能開拓更高效率、更高質量的軟件開發理念,誰就有條件在競爭中立于不敗之地。而工作流引擎正是競爭者具備這種條件的重要武器。相信工作流引擎將會發展成今后的開發平臺,在開發平臺上擁有自己的編程語言并可靈活地調用來自不同系統的程序接口,必將把軟件開發效率提升到新的高度。