工作流学习(二)

来源:互联网 发布:java面试宝典2017下载 编辑:程序博客网 时间:2024/05/16 16:57

Osworkflow简介

概念

Ø          在商用和开源世界里,OSWorkflow 都不同于这些已有的工作流系统。最大不同在于  OSWorkflow 有着非常优秀的灵活性。在开始接触 OSWorkflow 时可能较难掌握(有人说不适合工作流新手入门),比如, OSWorkflow 不要求图形化工具来开发工作流,而推荐手工编写 xml 格式的工作流程描述符。它能为应用程序开发者提供集成,也能与现有的代码 和数据库进行集成。这一切似乎给正在寻找快速即插即用工作流解决方案的人制造了麻烦,但研究发现,那些即插即用方案也不能在一个成熟的应用程序中 提供足够的灵活性来实现所有需求。

比较

Ø         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 Transtion(流转)到另外一个 Step,或者也可以在同一个 Step 内流转(因为 Step 可以通 Status 来细分,形成多个State)。一个流程里面可以多个Step

状态

Ø         工作流 Status 是用来描述工作流程中具体Step(步骤)状态的字符串。OSWorkflow 的有 Underway(进行中)、Queued (等候处理中)、Finished(完成)三种 Status。一个实际State(状态)真正是由两部分组成:State = (Step +  Status) 

流转

Ø          一个State到另一个State的转移。

动作

Ø         Action  触发了发生在 Step 内或 Step 间的流转,或者说是基于 State 的流转。一个 step 里面可以有多个ActionAction  Step 之间的关系是,Step 说明在哪里Action 说明去哪里 一个 Action 典型地由两部分组成:可以执行此Action (动作)的
Condition
(条件),以及执行此动作后的 Result(结果)。    

条件

Ø         类似于逻辑判断,可包含“AND”“OR”逻辑。比如一个请假流程中的本部门审批阶段,该阶段利用“AND”逻辑,判断流程状态是否为等候处理中,以及审批者是否为本部门主管。

结果

Ø         Result  代表执行Action(动作)后的结果,指向新的 Step 及其 Step Status,也可能进入 Split 或者 JoinResult  为两种, Contidional-Result (有条件结果),只有条件为真时才使用该结果,和 Unconditional-Result(无条件 结果),当条件不满足或没有条件时使用该结果。

分离/连接

Ø         流程的切分和融合。很简单的概念,Split 可以提供多个 Result(结果);Join 则判断多个 Current Step 的态提供一个 Result(结果)。

 

描述

步骤、状态和动作(Step, Status, and Action)

Ø         工作流要描述步骤(Step)、步骤的状态(Status)、各个步骤之间的关系以及执行各个步骤的条件和权限,每个步骤中可以含有一个或多个动作(Action),动作将会使一个步骤的状态发生改变。对 于一个执行的工作流来讲,步骤的切换是不可避免的。一个工作流在某一时刻会有一个或多个当前步骤,每个当前步骤都有一个状态值,当前步骤的状态值组成了工 作流实例的状态值。一旦完成了一个步骤,那么这个步骤将不再是当前步骤(而是切换到一个新的步骤),通常一个新的当前步骤将随之建立起来,以保证工作流继 续执行。完成了的步骤的最终状态值是用Old-Status属性指定的,这个状态值的设定将发生在切换到其他步骤之前。Old-Status的值可以是任 意的,但在一般情况下,我们设置为Finished。切换本身是一个动作(Action)的执行结果。每个步骤可以含有多个动作,究竟要 载入哪个动作是由最终用户、外部事件或者Tiggerd的自动调用决定的。随着动作的完成,一个特定的步骤切换也将发生。动作可以被限制在用户、用户组或 当前状态。每一个动作都必须包含一个Unconditional Result0个或多个Conditional Results。所 以,总体来说,一个工作流由多个步骤组成。每个步骤有一个当前状态(例如:Queued, Underway or Finished),一个步骤包含多 个动作。每个步骤含有多个可以执行的动作。每个动作都有执行的条件,也有要执行的函数。动作包含有可以改变状态和当前工作流步骤的results

 结果、分支和连接(Results, Joins, and Splits)

Ø         无条件结果(Unconditional Result)
对于每一个动作来讲,必须存在一个Unconditional Result。一个result是一系列指令,这些指令将告诉OSWorkFlow下一个任务要做什么。这包括使工作流从一个状态切换到另一个状态。

Ø         有条件结果(Conditional Result)
Conditional Result
Unconditional Result的一个扩展。它需要一个或多个Condition子标签。第一个为trueConditional(使用 ANDOR类型),会指明发生切换的步骤,这个切换步骤的发生是由于某个用户执行了某个动作的结果导致的。

Ø         三种不同的Results(conditional or unconditional)一个新的、单一的步骤和状态的组合。一个分裂成两个或多个步骤和状态的组合。将这个和其他的切换组合成一个新的单一的步骤和状态的组合。每种不同的result对应了不同的xml描述,注意:通常,一个split或一个join不会再导致一个split  join的发生。

 自动步骤(Auto actions)

Ø         的时候,我们需要一些动作可以基于一些条件自动地执行。为了达到这个目的,你可以在action中加入auto="true"属性。流程将考察这个动作的 条件和限制,如果条件符合,那么将执行这个动作。 Auto action是由当前的调用者执行的,所以将对该动作的调用者执行权限检查。

整合抽象实例(Integrating with Abstract Entities)

Ø         议在你的核心实体中,例如"Document"  "Order",在内部创建一个新的属性:workflowId。这样,当新的 "Document"  "Order"被创建的时候,它能够和一个workflow实例关联起来。那么,你的代码可以通过 OSWorkflow API查找到这个workflow实例并且得到这个workflow的信息和动作。

工作流实例状态(Workflow Instance State)

Ø         的时候,为整个workflow实例指定一个状态是很有帮助的,它独立于流程的执行步骤。OSWorkflow提供一些workflow实例中可以包含的 "meta-states"。这些"meta-states"可以是CREATED, ACTIVATED, SUSPENDED, KILLED   COMPLETED。当一个工作流实例被创建的时候,它将处于CREATED状态。然后,只要一个动作被执行,它就会自动的变成ACTIVATED 态。如果调用者没有明确地改变实例的状态,工作流将一直保持这个状态直到工作流结束。当工作流不可能再执行任何其他的动作的时候,工作流将自动的变成 COMPLETED状态。然而,当工作流处于ACTIVATED状态的时候,调用者可以终止或挂起这个工作流(设置工作流的状态为 KILLED  SUSPENDED)。一个终止了的工作流将不能再执行任何动作,而且将永远保持着终止状态。一个被挂起了的工作流会被冻结,他也不能 执行任何的动作,除非它的状态再变成ACTIVATED

 

Osworkflow

 OS_WFENTRY

工作流主表,存放工作流名称和状态

字段名        

数据类型

说明

ID    

NUMBER    

 自动编号

NAME    

VARCHAR2(20)    

工作流名称

STATE    

NUMBER    

工作流状态

 

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) 

 操作人员的帐号名称

 

OS_CURRENTSTEP_PREV

前步骤表,存放当前步骤和上一个步骤的关联数据

字段名        

数据类型

说明

ID   

 NUMBER   

当前步骤编号

PREVIOUS    

 NUMBER   

前步骤编号

 

 

 

 

OS_HISTORYSTEP

历史步骤表,存放当前正在进行步骤的数据

字段名        

数据类型

说明

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) 

 操作人员的帐号名称

 

 

 

 

OS_HISTORYSTEP_PREV

前历史步骤表,存放历史步骤和上一个步骤的关联数据

字段名        

数据类型

说明

ID   

 NUMBER   

当前步骤编号

PREVIOUS    

 NUMBER   

前步骤编号

 

 

 

 

OS_PROPERTYENTRY

属性表,存放临时变量

字段名        

数据类型

说明

GLOBAL_KEY   

VARCHAR2(255)    

    全局关键字

ITEM_KEY   

 VARCHAR2(255)    

   条目关键字

ITEM_TYPE    

 NUMBER   

    条目类型

STRING_VALUE    

 VARCHAR2(255)    

  字符值

DATE_VALUE    

  DATE    

    日期值

DATA_VALUE    

   BLOB    

   数据值

FLOAT_VALUE   

  FLOAT   

   浮点值

NUMBER_VALUE    

  NUMBER    

   数字值

 

Os_entryids

 

字段名        

数据类型

说明

id

bigint

编号

 

 

 

 

 

 

 

 

Os_stepids

 

字段名        

数据类型

说明

username

 

 

passwordhash

 

 

 

 

 

 

 

Os_group

 

字段名        

数据类型

说明

groupname

 

 

 

 

 

 

 

 

 

 

Os_membership

 

字段名        

数据类型

说明

Username

 

 

groupname

 

 

 

 

 

 

 

 

 

字段名        

数据类型

说明

 

 

 

 

 

 

 

 

 

 

Osworkflow程序包

 com.opensymphony.workflow

Ø         该包为整个OSWorkflow 引擎提供核心接口。例如 com.opensymphony.workflow.Workflow 接口,可以说,实际开 发中的大部分工作都是围绕该接口展开的,该接口有 BasicWorkflowEJBWorkflowOfbizWorkflow 三个实现类。

 com.opensymphony.workflow.basic

Ø         该包有两个类,BasicWorkflow  BasicWorkflowContextBasicWorkflow 不支持事务,尽管依赖持久实现,事务也不能包裹它。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 setWorkflow(int userId) {
    Workflow workflow = new BasicWorkflow(Integer.toString(userId));
}

 

 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 方法来得到最终查询结 果。

com.opensymphony.workflow.soap

Ø         OSWorkflow 通过 SOAP 来支持远端调用。这种调用借助 WebMethods 实现。

 

 com.opensymphony.workflow.spi

Ø         该包可以说是 OSWorkflow 与持久层打交道的途径,如当前工作流的实体,其中包括:EJBHibernateJDBCMemoryOfbizOJBPrevayler

HibernateWorkflowEntry hwfe = (HibernateWorkflowEntry) getHibernateTemplate()
    .find("from HibernateWorkflowEntry where Id="
        + wfIdList.get(i)).get(0);

com.opensymphony.workflow.util

Ø         该包是 OSWorkflow 的工具包,包括了对 BeanShellBSFEJB LocalEJB RemoteJNDI 的支持。

 

Basic

Basicworkflow:未实现事务回滚

Basicworkflowcontext:上下文对象的basic实现方式

Config

读取xml配置文件的一些常用类

Ejb

Workflowejb实现方式,主要对象是ejbworkflowejbworkflowcontext

loader

在工作流初始化时必须要加载的一些类。主要有workflowfactory接口xmlworkflowfactory实现类,还有workflowdescriptor等描述xml配置文件的实体对象

Ofbiz

Workflowofbiz实现方式,只有两个对象分别是ofbizworkflowofbizworkflowcontext

Query

查询分析器,完成单一、嵌套、组合查询,主要对象workflowExpressionquery

Soap

Soap实现方式

Spi

与后台打交道的关于workflow存储的一些类或者对象有workflowentry接口,此接口返回一个工作流实例对象;workflowstore里面定义的全部都是工作流的存储和查询方法;

JDBCworkflowstore实现simpleworkflowentry

Hibernate或者spring+hibernate实现hibernateworkflowentry

Step接口被simplestep或者hibernatestep调用;

Simplestepjdbcworkflowstep实现方式;

Hibernatestephibernateworkflowstore或者springhibernaterkflow实现方式

Spi.ejb

Ejb方式存储

Spi.hibernate

Hibernate2或者spring+hibernate2形势存储实现方式

Spi.hibernate3

Hibernate3或者spring+hibernate3形势存储实现方式,目前主流方式

Spi.jdbc

Jdbc存储方式,常见且经典方式

Spi.memory

Memory存储方式

Spi.ofbiz

Ofbiz形势存储方式

Spi.ojb

Obj存储方式

Spi.prevayler

Prevayler存储方式

Timer

定时器,用来处理定时任务

util

扩展,实现支持jndijmailspringframeworklog4josuer

Util.beanshell

Beanshell形势的conditionfunctionregistorvalidator实现方式

Util.bsf

Bsf形势的conditionfunctionregistorvalidator实现方式

Util.ejb

Ejb形势的conditionfunctionregistorvalidator实现方式

Util.jndi

Jndi形势的conditionfunctionregistorvalidator实现方式

 

Osworkflow方法接口

WorkflowinitializedoAction,还有wfGetAvailableActions(id,map)方法都有一个hashmap类型参数,是用来传递工作流中所需的数据或者对象,其有效范围只包括当前步骤或者下一步。可应用在function,condition,validator等当中

 

Workflow主要方法

getAvailableActions(id,null)

得到当前工作流实例所有有效动作

ID:工作流实例ID

要传递的对象

getCurrentSteps(id)

得到当前步骤

getEntryState(id)

得到当前状态

getHistorySteps(id)

得到历史步骤

getPropertySet(id)

得到PropertySet对象

getSecurityPermissions(id)

得到状态权限列表

getWorkflowDescriptor(id)

得到工作流XML描述文件对象

getWorkflowName(id)

得到当前实例名称

getWorkflowNames()

得到工作流名称

 

 

 

Workflow接口中的核心方法

Ø         得到workflowstore实现类,利用里面的createEntry方法创建一个workflowentry对象

Ø         执行populateTransientMap方法,将contextworkflowcontext),entryworkflowentry),stroreworkflowstore),configurationconfiguration),descriptorworkflowDescriptor)装进transientvars;将当前要执行的actionidcurrentsteps装进transientvars;将所有XML中配置的register装进transientvars

Ø         根据restrict-to里配置的条件来判断是否能初始化工作流,如果不能则回滚并抛出异常

Ø         执行transitionworkflow方法传递工作流,这个transitionworkflow方法是workflow中重要方法

Ø         返回当前工作流程实例ID

 

Transition workflow方法

是工作流最核心的方法,它主要是完成以下功能

Ø         利用getCurrentStep方法取得当前步骤:如果只有一个有效步骤,直接返回;如果有多个有效当前步骤,返回符合条件的第一个

Ø         调用动作验证器来验证transientvars里面的变量

Ø         执行当前步骤中的所有post-function

Ø         执行当前动作中的所有pre-function

Ø         检查当前动作中的所有有条件结果,如果符合条件,验证transientvars里面的变量并执行有条件结果里面的pre-function;如果动作里面没有一个有条件结果,执行无条件结果,验证transientvars里面的变量并执行无条件结果里面的pre-function

Ø         如果程序进入到一个split中:1)验证transientvars里面的变量;2)执行split中的pre-function3)如果动作中的finish不等于true,执行split中所有result4)结束当前步骤并将其移到历史步骤中去,创建新的步骤并执行步骤中的pre-function5)执行split中的post-function

Ø         如果进入join1)结束当前步骤并将其移入历史步骤中;2)将刚结束的步骤和在join中的当前步骤还有历史步骤夹道joinsteps集合中并产生joinnodes对象,将此对象puttransientvars里;3)检查join条件;4)执行join条件结果中的validator5)执行join有条件结果中的pre-function6)如果当前步骤不再历史步骤里面,把它移到历史步骤里面去;7)如果刚刚结束的当前动作中的finish不等于true,创建新步骤并执行新步骤中的pre-function8)执行joinpost-function

Ø         如果程序进入到另一个step中:结束当前步骤并将其移到历史步骤中去,并创建新的步骤并执行新步骤中的pre-function

Ø         如果动作里面有符合条件的有条件结果,执行有条件结果里面的post-functioin;如果动作里面没有一个有条件结果,则执行无条件结果里面的post-function

Ø         执行动作里面的post-function

Ø         如果动作一开始是一个初始化状态,将设置activated标识,如果动作在XML里面有完成状态的标识,将设置compleleted标识

Ø         执行有效的自动动作(auto action

Ø         最后返回流程是否完成的布尔值:如果流程实例已经完结,返回true;否则返回false

 

 

DoAction方法

Ø         判断工作流的实例状态,如果状态不为activated1),直接返回

Ø         利用findCurrentsteps方法得到当前所有步骤列表

Ø         执行populatetransientmap方法,将contextworkflowcontext),entryworkflowentry),stroreworkflowstore),configurationconfiguration),descriptorworkflowDescriptor)装进transientvars;将当前要执行的actionidcurrentsteps装进transientvars;将所有XML中配置的register装进transientvars

Ø         检查全局动作(Global Action)和当前步骤里面所有动作的有效性。如果有无效动作,直接抛出异常

Ø         执行transientionworkflow方法传递工作流,如果捕获到workflowexception,抛出异常并回滚

Ø         如果动作中没有显示地表明finish的状态true,那么这时要执行checkimplicitfinish方法,查找当前步骤中是否还有有效动作,如果没有一个有效动作,则直接调用completeentry方法结束流程并将流程的状态设置为completed4

 

workflowDescriptor对象里面的主要方法

getAction(id)

根据动作ID得到当前动作描述信息

getCommonActions()

得到通用动作列表

getGlobalActions()

得到全局动作列表

getGlobalConditions()

得到全局条件类标

getInitialAction(id)

根据初始动作ID得到初始动作描述信息

getInitialActions()

得到所有动作描述信息

getJoin(id)

得到联合描述信息

getJoins()

得到所有联合描述信息

getName()

得到工作流描述文件名称

getRegisters()

得到所有注册器

getSplit(id)

根据分支ID得到分支描述信息

getSplits()

得到所有分支描述信息

getStep(id)

根据步骤ID得到步骤描述信息

getSteps()

得到所有步骤描述信息

getTriggerFunction(id)

根据触发ID得到触发描述信息

getTriggerFunctions()

得到所有触发描述信息