前 言
??? 本文沒有拋出可運行的范例,僅僅是程序片斷而已,不過在 OSWorkflow 的 Wiki 上,Quake Wang 已把官方入門教程完整地翻譯成中文了,有興趣的讀者可去閱讀。關于 OSWorkflow 更加細節性的內容,可參考官方手冊,相信你在了解了入門教程后,可輕松閱讀官方手冊。
???
OSWorkflow 概念
??? 在商用和開源世界里,OSWorkflow 都不同于這些已有的工作流系統。最大不同在于 OSWorkflow 有著非常優秀的靈活性。在開始接觸 OSWorkflow 時可能較難掌握(有人說不適合工作流新手入門),比如,OSWorkflow 不要求圖形化工具來開發工作流,而推薦手工編寫 xml 格式的工作流程描述符。它能為應用程序開發者提供集成,也能與現有的代碼和數據庫進行集成。這一切似乎給正在尋找快速“即插即用”工作流解決方案的人制造了麻煩,但研究發現,那些“即插即用”方案也不能在一個成熟的應用程序中提供足夠的靈活性來實現所有需求。
???
OSWorkflow 優勢
??? OSWorkflow 給你絕對的靈活性。OSWorkflow 被認為是一種“低級別”工作流實現。與其他工作流系統能用圖標表現“loops(回路)”和“conditions(條件)”相比,OSWorkflow 只是手工“編碼(coded)”來實現的。但這并不能說實際的代碼是需要完全手工編碼的,腳本語言能勝任這種情形。OSWorkflow 不希望一個非技術用戶修改工作流程,雖然一些其他工作流系統提供了簡單的 GUI 用于工作流編輯,但像這樣改變工作流,通常會破壞這些應用。所以,進行工作流調整的最佳人選是開發人員,他們知道該怎么改變。不過,在最新的版本中,OSWorkflow 也提供了 GUI 設計器來協助工作流的編輯。
??? OSWorkflow 基于有限狀態機概念。每個 state 由 step ID 和 status 聯合表現(可簡單理解為 step 及其 status 表示有限狀態機的 state)。一個 state 到另一 state 的 transition 依賴于 action 的發生,在工作流生命期內有至少一個或多個活動的 state。這些簡單概念展現了 OSWorkflow 引擎的核心思想,并允許一個簡單 XML 文件解釋工作流業務流程。
OSWorkflow 核心概念
???
step(步驟)
??? 一個 step 是工作流所處的位置。可能從一個 step 流轉到另外一個 step(或者有時候還是停留在一樣的 step)。舉例來說,一個 OA 系統的請假流程,它的 step 名稱可能有“本部門審批階段”,“辦公室審批階段”,“總經理審批階段”等。
?
status(狀態)
??? 工作流 status 是一個用來描述工作流程中具體步驟狀態的字符串。OSWorkflow 的有 Underway(進行中)、Queued(等候處理中)、Finished(完成)三種 status。
?
action(動作)
??? action 指定了可能發生在 step 內的轉變,會導致 step 的變更。在 OA 系統中,“本部門審批階段”可能有“拒絕”或“批準”兩個 action。action 和 step 之間的關系是,step 說明“在哪里”,action 說明“可以去哪里”。 一個 action 典型地由兩部分組成:可以執行此動作的 condition(條件),以及執行此動作的 result(結果)。
?
condition(條件)
??? 類似于邏輯判斷,可包含“AND”和“OR”邏輯。比如一個請假流程中的“本部門審批階段”,該階段利用“AND”邏輯,判斷流程狀態是否為等候處理中,以及審批者是否為本部門主管。
???
result(結果)
??? Result 代表指向新的 step 及其 step status,也可能進入 split 或者 join。Result 分為兩種, contidional-result (有條件結果),只有條件為真時才使用該結果,和 unconditional-result(無條件結果),當條件不滿足或沒有條件時使用該結果。
split/join(分離/連接)
流程的切分和融合。很簡單的概念,split 提供多個 result;join 則判斷多個 current step 的狀態,提供一個 result。
OSWorkflow 包用途分析及代碼片斷
???
com.opensymphony.workflow
??? 該包為整個 OSWorkflow 引擎提供核心接口。例如 com.opensymphony.workflow.Workflow 接口,可以說,實際開發中的大部分工作都是圍繞該接口展開的,該接口有 BasicWorkflow、EJBWorkflow、OfbizWorkflow 三個實現類。
com.opensymphony.workflow.basic
??? 該包有兩個類,BasicWorkflow 與 BasicWorkflowContext。BasicWorkflow 不支持事務,盡管依賴持久實現,事務也不能包裹它。BasicWorkflowContext 在實際開發中很少使用。
??public void setWorkflow(int userId) { ??Workflow workflow = new BasicWorkflow(Integer.toString(userId)); ?}
|
com.opensymphony.workflow.config
??? 該包有一個接口和兩個該接口的實現類。在 OSWorkflow 2.7 以前,狀態由多個地方的靜態字段維護,這種方式很方便,但是有很多缺陷和約束。最主要的缺點是無法通過不同配置運行多個 OSWorkflow 實例。實現類 DefaultConfiguration 用于一般的配置文件載入。而 SpringConfiguration 則是讓 Spring 容器管理配置信息。
??public void setConfiguration(SpringConfiguration configuration) { ??SpringConfiguration configuration = configuration; workflow.setConfiguration(configuration); ?}
|
com.opensymphony.workflow.ejb
??? 該包有兩個接口 WorkflowHome 和 WorkflowRemote。該包的若干類中,最重要的是 EJBWorkflow,該類和 BasicWorkflow 的作用一樣,是 OSWorkflow 的核心,并利用 EJB 容器管理事務,也作為工作流 session bean 的包裝器。
com.opensymphony.workflow.loader
??? 該包有若干類,用得最多的是 XxxxDescriptor,如果在工作流引擎運行時需要了解指定的動作、步驟的狀態、名字,等信息時,這些描述符會起到很大作用。
??public String findNameByStepId(int stepId,String wfName) { ??WorkflowDescriptor wd = workflow.getWorkflowDescriptor(wfName); ??StepDescriptor stepDes = wd.getStep(stepId); ??return stepDes.getName(); ?}
|
com.opensymphony.workflow.ofbiz
??? OfbizWorkflow 和 BasicWorkflow 在很多方面非常相似,除了需要調用 ofbiz 的 TransactionUtil 來包裝事務。
com.opensymphony.workflow.query
??? 該包主要為查詢而設計,但不是所有的工作流存儲都支持查詢。通常,Hibernate 和 JDBC 都支持,而內存工作流存儲不支持。值得注意的是 Hibernate 存儲不支持混合型查詢(例如,一個查詢同時包含了 history step 上下文和 current step 上下文)。執行一個查詢,需要創建 WorkflowExpressionQuery 實例,接著調用 Workflow 對象的 query 方法來得到最終查詢結果。
??public List queryDepAdmin(int userId,int type) { ??int[] arr = getSubPerson(userId,type);
??//構造表達式 ??Expression[] expressions = new Expression[1 + arr.length]; ??Expression expStatus = new FieldExpression(FieldExpression.STATUS, ????FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, "Queued"); ??expressions[0] = expStatus;
??for (int i = 0; i < arr.length; i++) { ???Expression expOwner = new FieldExpression(FieldExpression.OWNER, ?????FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, ?????Integer.toString(arr[i])); ???expressions[i + 1] = expOwner; ??}
??//查詢未完成流編號 ??List wfIdList = null; ??try { ???WorkflowExpressionQuery query = new WorkflowExpressionQuery( ?????new NestedExpression(expressions, NestedExpression.AND)); ???wfIdList = workflow.query(query); ??} catch (Exception e) { ???e.printStackTrace(); ??}
|
com.opensymphony.workflow.soap
??? OSWorkflow 通過 SOAP 來支持遠端調用。這種調用借助 WebMethods 實現。
com.opensymphony.workflow.spi
??? 該包可以說是 OSWorkflow 與持久層打交道的途徑,如當前工作流的實體,其中包括:EJB、Hibernate、JDBC、Memory、Ofbiz、OJB、Prevayler。
??HibernateWorkflowEntry hwfe = (HibernateWorkflowEntry) getHibernateTemplate() ?????.find("from HibernateWorkflowEntry where Id=" ?????????+ wfIdList.get(i)).get(0); |
com.opensymphony.workflow.util
該包是 OSWorkflow 的工具包,包括了對 BeanShell、BSF、EJB Local、EJB Remote、JNDI 的支持。
小 結
??? 由于本人所在公司希望在 OA 系統中引入工作流引擎,經過分析決定采用 OSWorkflow 引擎。利用 OSWorkflow,已經在系統中實現了請假條流程原型,該流程結合 OA 系統中已有的 RBAC 模型進行逐級審核。我個人認為要用 OSWorkflow 讓某個流程跑起來似乎很麻煩,主要是需要擴展和自己實現的太多。
???
??? 另外,引用一段 Quake Wang 的原話:電子政務/OA 如果要使用workflow engine的話,shark,jbpm 之類的workflow engine有點殺雞用牛刀的味道。shark 和 jbpm 都強迫你使用它的用戶模型,怎樣把企業現有的用戶模型(包括組織結構)映射過來是很繁瑣的事情,比如常見的 OA 應用中,申請者對應的部門負責人為下一個流程的人工參與者,使用 shark 或者 jbpm 都得繞一圈,通過現有的人力資源系統,獲得用戶,再對應過來。這還僅僅是一個簡單的需求,更不用說國內企業千奇百怪的組織結構,以及各種特殊流程,用 wfmc 或者其他所謂的 workflow 通用標準去做不怎么標準的事情。吃力不討好。用 osworkflow 這種基于狀態機的 workflow engine 反而會輕松很多,而且它也沒有強迫你使用它的用戶模型。另外糾正一點:osworkflow 不僅僅支持簡單的 BeanShell,還支持 java class,bsf,ejb。如果做電子政務/OA 的話,覺得目前 osworkflow 是最適用的 opensource workflow engine。
原作者:Rosen Jiang 以及出處:http://www.tkk7.com/rosen