一、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 前步骤编号