OSWorkflow之一——初步印象

OSWorkflow不是一种开箱即用的工作流解决方案,要想让OSWorkflow能更好的为我们服务,我们还需要做一些编码相关的工作,因此他可以很灵活的实现各种各样的复杂流程。你可以把这看做是OSWorkflow的优点,但作为优点的同时,这也是他的缺点,因为也许这样额外的工作并不是你想要的,你可能需要一些相对简单一点的工作方式,这就需要大家自己去权衡啦!

我们准备使用Spring的相关特性,也许还有Hibernate,所以我们探讨的重点会放在这些方面。

初步印象

OSWorkflow是通过XML来完成流程的定制化的。下面是一个流程定义的例子,让我们先建立一个初步的印象。

图1:

example.xml

从这张图上,我们能看到一个流程的原型:一个流程(workflow)我们可以定制他的初始行为(initial-actions ),他包括哪些步骤(steps ),每个步骤下面我们还可以有很多行为(actions ),这些行为他可以有自己的约束条件(restrict-to ),同时我们还看到了一些前置(pre-functions )或者后置处理(post-functions ),每个行为(action)也都有自己的结果(results ),当所有步骤都结束时,这个流程的生命周期也就结束啦。当然我们还可以定义多个流程,就像这样:

图2:

workflows.xml

 我们可以定义多个像图1那样的流程文件,像图2所示的那样定义到workflows元素中去。

OSWorkflow流程的流转

  1. 建立一个workflow(流程)时,我们需要指定workflow的名称(如图2中的“example”),这是因为我们可以定义很多个workflow的规则,各个不同的workflow之间,OSWorkflow通过workflow的name来区别。这样,我们一个name=example的workflow的一个实例就被创建了。
  2. 任何一个workflow启动时,都需要有一个initialAction(初始行为)。当workflow被建立时,这个initialAction将会根据自身的配置规则来判断是否可以被执行,当条件都满足时initialAction将被执行。
  3. initialAction执行后workflow会来到一个初始step(步骤),一个workflow是由多个step组成的,他就像是一个状态机,有自己的stepId和status。但是step本身是一种静态的描述,他自己并不会流转,一个step向另一个step流转是通过action(动作行为)来完成的。

我们通过一个简单的例子来更深入的了解和学习OSWorkflow,并构建我们自己的工作流引擎。

从一个简单的流程定义开始:

example.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.6//EN" "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">
<workflow>
	<initial-actions>
		<action id="100" name="Start Workflow">
			<pre-functions>
				<function type="class">
					<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
				</function>
			</pre-functions>
			<results>
				<unconditional-result old-status="Finished" status="Underway" step="1" owner="${caller}"/>
			</results>
		</action>
	</initial-actions>
	<steps>
		<step id="1" name="First Draft">
			<actions>
				<action id="1" name="Finish First Draft">
					<pre-functions>
						<function type="beanshell">
							<arg name="script">
                                String caller = context.getCaller();
                                propertySet.setString("caller", caller);
                                boolean test = true;
                                String yuck = null;
                                String blah = "987654321";
                                System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
                            </arg>
						</function>
					</pre-functions>
					<results>
						<unconditional-result old-status="Finished" status="Finished" step="-1"/>
					</results>
					<post-functions>
						<function type="spring">
							<arg name="bean.name">myFunction</arg>
						</function>
					</post-functions>
				</action>
			</actions>
		</step>
	</steps>
</workflow>

 

workflows.xml

<workflows>
    <workflow name="example" type="resource" location="example.xml"/>
</workflows>

 我们可以在workflows元素中定义多个workflow,这里我们只有一个example.xml

osworkflow.xml

<osworkflow>
    <persistence class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/>

    <factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
        <property key="resource" value="workflows.xml" />
    </factory>
</osworkflow>
  

 osworkflow.xml是OSWorkflow的基础配置,我们之前的配置文件,最后通过WorkflowFactory的resource关联起来了。

认识Configuration

Configuration接口有两个实现类,分别是DefaultConfiguration和SpringConfiguration,我们打算使用Spring的相关特性,我们就从SpringConfiguration说起。

图3:

我们看Configuration接口,会不会有一种似曾相识的感觉,尤其是看SpringConfiguration中的factory和store,怎么看都和osworkflow.xml中的factory、persistence如此相似,这不就是osworkflow.xml的定义嘛!

WorkflowFactory

WorkflowFactory接口定义了一些常用的关于Workflow的增删改查操作,可以说他掌握了Workflow的生杀大权。

图4:

上图是我们将会重点关注的一些类的定义,因为他们和Spring的关系比较密切,WorkflowFactor的族谱其实要丰富得多。不难看出,XMLWorkflowFactory基本上完成了WorkflowFactory接口的所有实现,而SpringWorkflowFactory只新引入了一个resource属性,用来保存workflows.xml文件的路径,看来如果通过XML的方式定义流程,XMLWorkflowFactory才是幕后的支持者。

WorkflowStore

WorkflowStore接口里定义了workflow实例持久化相关的操作。在OSWorkflow中一共定义了两个AbstractHibernateWorkflowStore抽象类及其对应的实现,用来支持不同版本的hibernate。一个在hiberna包中,一个在hibernate3包中。所以在使用过程中,我们要注意他们的完整类名。这里主要介绍的是hibernate3的相关支持。

AbstractHibernateWorkflowStore有两个子类,分别是HibernateWorkflowStore和SpringHibernateWorkflowStore,其中前者是单一的hibernate3的实现,而后者是在Spring下的hibernate3实现。


图5:

上图中还列出了JDBCWorkflowStore的相关实现,这也是OSWorkflow给我们的最早的WorkflowStore实现,我们可以根据情况选择使用。

对比WorkflowStore和WorkflowFactory两个接口,好像他们都是对workflow进行增删改查操作,但他们是不同的。WorkflowFactory中引入了一个WorkflowDescriptor类,而WorkflowStore中则是强调WorkflowEntry类。WorkflowDescriptor他是workflow关于XML描述的类型定义,OSWorkflow把定义在XML中的流程,根据DTD文件中定义好的各种XML元素,抽象出了很多种Descriptor(后面介绍),WorkflowFactory则针对的是WorkflowDescriptor。

XML中定义的流程只是一种Descriptor,他是这个流程的蓝图,而WorkflowEntry则是流程的一个个实例。如果我们定义了一个关于文件审批的流程,若干个文件在这个审批流程的生命周期中审批,他们每一个文件都会对应着这个流程的一个实例,WorkflowStore则是负责WorkflowEntry的CRUD工作。

至此,我们分析了Configuration、WorkflowFactory、WorkflowStore他们各自的职业以及他们三者的关系。

Configuration:与osworkflow.xml对应,同时定义了WorkflowFactory和WorkflowStore;

WorkflowStore:负责workflow实例的CRUD工作;

WorkflowFactory:创建和管理WorkflowDescriptor,是我们流程的发源地。

应用集成

<bean id="workflowStore"
		class="com.opensymphony.workflow.spi.hibernate3.SpringHibernateWorkflowStore">
		<property name="sessionFactory">
			<ref bean="sessionFactory" />
		</property>
	</bean>

	<bean id="workflowFactory"
		class="com.opensymphony.workflow.spi.hibernate.SpringWorkflowFactory"
		init-method="init">
		<property name="resource">
			<value>workflows.xml</value>
		</property>
		<property name="reload">
			<value>false</value>
		</property>
	</bean>

	<bean id="osworkflowConfiguration" class="com.opensymphony.workflow.config.SpringConfiguration">
		<property name="store">
			<ref local="workflowStore" />
		</property>
		<property name="factory">
			<ref local="workflowFactory" />
		</property>
	</bean>
 

猜你喜欢

转载自kt8668.iteye.com/blog/1144579