一、Osworkflow兩個重要的概念:
steps:步驟
actions:動作
initial-actions:初始化步驟
1、steps步驟:描述一個工作流所處的位置
2、actions:指定了可能發生在步驟內的轉變,一個step包含多個action,一個action由兩部分組成:執行此條件的condition及執行此動作后的result
3、initial-actions:初始化步驟,是一種特殊的步驟,用來啟動工作流
二、屬性:
old_status:用來指明當前步驟完成以后的狀態是什么
status:指明需要檢查的狀態條件,目前Osworkflow中有underway進行中、queued等候處理中、Finished完成三種狀態
conditon:類似邏輯判斷,可包含"and"、"or"邏輯
result:執行action后的結果,分兩種,Conditional-result有條件結果、Unconditional-result無條件結果
split、join:流程的切分/融合,split可以提供多個result,join根據多個step的狀態提供一個result
三、函數:
Caller:Osworkflow提供的內置函數,該函數獲得當前調用工作流的用戶,並放入一個名為caller的字符型變量中
四:運行:
1、首先需要定義以下幾個文件:
osworkflow.xml:
<?xml version="1.0" encoding="UTF-8"?>
<osworkflow>
<factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
<property key="resource" value="workflows.xml"/>
</factory>
</osworkflow>
<osworkflow>有一個屬性:<persistence class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/>表示使用內存存儲流程數據
XMLWorkflowFactory:管理流程定義文件,包括讀取定義文件及修改定義文件的功能,resource指定讀取定義文件的位置
workflows.xml:
<?xml version="1.0" encoding="UTF-8"?>
<workflows>
<workflow name="vc_audit" type="resource" location="osworkflow/vc_audit.xml"></workflow>
</workflows>
2、執行步驟如下(參考)
為了簡單起見,我們采用BasicWorkflow來創建一個單一的用戶模式,避免編寫其他獲取用戶方法的麻煩。
這樣我們來創建一個'testuser'調用的workflow:
Workflow workflow = new BasicWorkflow("testuser");
下一步是提供配置文件,在大多數情況下,只是簡單的傳遞一個DefaultConfiguration實例:
DefaultConfiguration config = new DefaultConfiguration();
workflow.setConfiguration(config);
現在我們已經創建並且配置好了一個workflow,接下來就是開始調用它了。
啟動和進行一個工作流程
首先我們需要調用initialize 方法來啟動一個工作流程,這個方法有3個參數,workflow name (定義在workflows.xml里,通過workflow factory處理), action ID (我們要調用的初始化動作的ID),和初始化變量。 因為在例子里面不需初始化變量,所以我們只是傳遞一個null,
long workflowId = workflow.initialize("mytest", 1, null);
我們現在已經有了一個工作流實例,返回的workflowId可以在后續的操作中來代表這個實例。這個參數會在Workflow interface的絕大部分方法中用到。
檢驗工作流
現在讓我們來檢驗啟動的工作流實例是否按照我們所預期的那樣運行。根據流程定義,我們期望的當前步驟是第一步,而且應該可以執行第一個動作(開始編寫草稿)。
Collection currentSteps = workflow.getCurrentSteps
(workflowId);
//校驗只有一個當前步驟
assertEquals("Unexpected number of current steps",
1, currentSteps.size());
//校驗這個步驟是1
Step currentStep = (Step)currentSteps.iterator().next();
assertEquals("Unexpected current step", 1,
currentStep.getStepId());
int[] availableActions =
workflow.getAvailableActions(workflowId);
//校驗只有一個可執行的動作
assertEquals("Unexpected number of available actions", 1,
availableActions.length);
//校驗這個步驟是1
assertEquals("Unexpected available action", 1, availableActions[0]);
執行動作
現在已經校驗完了工作流實例正如我們所期望的到了第一個步驟,讓我們來開始執行第一個動作:
workflow.doAction(workflowId, 1, null);
這是簡單的調用第一個動作,工作流引擎根據指定的條件,改變狀態到‘Underway’,並且保持在當前步驟。
現在我們可以類似地調用第2個動作,它所需要的條件已經都滿足了。
在調用完第2個動作以后,根據流程定義就沒有可用的動作了,getAvailableActions將會返回一個空數組。
五、property set
1、PropertySet:有時候可能需要在工作流的任意位置持久化一些少量數據,PropertySet作用就是如此,是一個可持久化的類型安全map,可以添加任意類型數據到propertyset(一個工作流實例對應一個propertyset),並在以后的流程中讀取這些數據,用法如下:
<function type="beanshell">
<arg name="script">propertySet.setString("foo", "bar")</arg>
</function>
這樣我們就添加了一個持久化的屬性“foo”,它的值是“bar”。這樣在以后的流程中,我們就可以獲得這個值了。
2、transient map :臨時變量
只在當前工作流調用的上下文中有效,workflow.doAction(workflowId, 1, null);如果傳入不是null的話就會存到臨時變量中
3、register寄存器:
一個工作流的全局變量,和propertyset類似,可以在工作流實例的任意地方獲取,與propertyset不同的地方是,它是一個非持久化的一個數據,每次調用都需要重新計算數據,寄存器的值存放在臨時變量transient map中,須實現Register接口,並且定在在初始化動作之前
六、
OSWorkFlow表結構分析
1、OS_WFENTRY 工作流主表,存放工作流名稱和狀態
字段名 數據類型 說明
ID NUMBER 自動編號
NAME VARCHAR2(20) 工作流名稱
STATE NUMBER 工作流狀態
2、OS_CURRENTSTEP當前步驟表,存放當前正在進行步驟的數據
字段名 數據類型 說明
ID NUMBER 自動編號
ENTRY_ID NUMBER 工作流編號
STEP_ID NUMBER 步驟編號
ACTION_ID NUMBER 動作編號
OWNER VARCHAR2(20) 步驟的所有者
START_DATE DATE 開始時間
FINISH_DATE DATE 結束時間
DUE_DATE DATE 授權時間
STATUS VARCHAR2(20) 狀態
CALLER VARCHAR2(20) 操作人員的帳號名稱
3、 OS_CURRENTSTEP_PREV 前步驟表,存放當前步驟和上一個步驟的關聯數據
字段名 數據類型 說明
ID NUMBER 當前步驟編號
PREVIOUS NUMBER 前步驟編號
