一个workflow有许许多多的step组成,而一个step到另一个step的流转是通过action来完成的。
我们先来看看actions的DTD声明
<!-- A list of zero or more common-actions and a list of zero or more actions for the enclosing step. Note that you must define one or the other, an actions element with neither will be considered invalid. Used in: step --> <!ELEMENT actions (common-action*, action*)>
actions的父节点是step,从声明中可以看出,我们可以在他的下面定制各种各样的common-action和action
从action说起
下面是action的定义
<!ELEMENT action (meta*, restrict-to? , validators?, pre-functions?, results, post-functions?)> <!ATTLIST action id CDATA #REQUIRED name CDATA #REQUIRED view CDATA #IMPLIED auto (TRUE | FALSE | true | false) #IMPLIED finish (TRUE | FALSE | true | false) #IMPLIED >
Attributes:
id: 标识符,在整个流程定义中,他必须唯一
name: 名称
view: a view name for the action
auto: 可选值(true|false),如果为true的话,这个action将在条件满足后会被自动执行,默认值false
finish: 可选值(true|false),默认值false
Action执行的Condition
Condition接口只有一个passesCondition方法,返回值是boolean,只有返回true的时候,我们的Action才可能被后续执行。下面是passesCondition的方法签名:
public boolean passesCondition(Map transientVars, Map args, PropertySet ps) throws WorkflowException;
passesCondition参数:
A、transientVars
作为一个Map类型的参数,他内部保存了一些内置的key-value,同时他也能保存着我们希望他保存的东西(我们可以通过在调用OSWorkflow的API的时候作为参数传递给他,稍后介绍)。
transientVars中的内置变量:
1、createdStep:新建Step的相关信息,保存的是Step接口的实现
2、currentSteps:保存当前的steps
3、descriptor:Workflow的Descriptor信息,保存的是WorkflowDescriptor实例
4、context:Workflow的上下文信息,保存的是WorkflowContext接口实现
5、entry:保存当前WorkflowEntry的实例
6、store:保存当前存储方式
7、configuration:保存Configuration接口的实现——DefaultConfiguration实例
8、actionId:保存当前actionId
9、jn:保存JoinNodes信息
他承载着以上的这些内置变量以及doAction方法的Map类型参数的值,并作为以下这些方法的参数在整个流程中共享和传递。
1、Condition接口的passesCondition方法,我们可以实现Condition接口来自定义条件,并配置到流程文件中的各种condition元素中去
2、Validator接口的validate方法,我们可以实现Validator接口来自定义验证器,并配置到流程文件中的各种validator元素中去
3、FunctionProvider接口的execute方法,我们可以实现FunctionProvider接口来自定义各种方法,并配置到流程文件中的各种function元素中去
这三个方法作为OSWorkflow流程最常见的扩展点,我们可以在自己实现相关接口的同时获取到这些变量信息,配合我们完成相关需求的实现。
B、args
我们先看一个流程定制文件的片段
<condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Queued</arg> </condition>
args参数保存的就是在以上代码片段中的两个关于arg元素的配置部分的信息,我们可以在passesCondition方法中通过
args的get("status")方法或者相关参数的值。
C、ps
该参数对应的参数类型为com.opensymphony.module.propertyset.PropertySet,他可以将一些类型的变量以key-value的方式持久化到存储设备中去。我们以MYSQL数据库为例,看看他的庐山真面目
图1:
前三列为联合主键,entity_key是我们的key名称,对应的值则保存在key_type以后的那些列中,根据value值的类型不同来确定保存在哪一列中。
我们需要引入下面jar来支持PropertySet
propertyset-1.5.jar:基础包
propertyset-hibernate3-1.5.jar:通过hibernate的方式来持久化数据,这个包里有一个PropertySetItemImpl.hbm.xml的映射文件,可以根据情况使用。
内置的Condition
OSWorkflow给我们提供了一些Condition可以供我们直接使用。
图2:
其中AllowOwnerOfStepCondition、AllowOwnerOnlyCondition、DenyOwnerCondition已经被deprecated掉了,不推荐使用,而是用IsUserOwnerCondition替代啦。
IsUserOwnerCondition
IsUserOwnerCondition作为一个内置的Condition,他返回当前workflow实例的caller和owner的匹配结果。如果相等则返回true,否则为false。
BeanShellCondition
http://www.beanshell.org/
beanshell可以在嵌入到系统中,就像在执行脚本语言一样,在系统运行时动态的执行JAVA代码。我们也可以通过BeanShell调用我们的应用程序及其对象,它可以让JAVA对象和API动态运行。BeanShell是用JAVA写的,所以它可以和你的应用程序运行在同一个JVM空间内,我们也可以自由的传递实时对象的References到脚本代码中,调用相关方法并且作为结果返回。
以下是一个简单的配置例子,直接返回true
<condition type="beanshell"> <arg name="script">true</arg> </condition>
注意:
<arg name="script">我们的代码在这里</arg>
BSFCondition
Bean Scripting Framework(B