嵌入式工作流引擎的设计与应用

2009-03-23 02:40许悦珊
计算机时代 2009年1期

许悦珊

摘要:计算机硬件需要中央处理器,而计算机软件则需要中央控制器—工作流引擎。工作流引擎不但可以灵活控制软件的业务逻辑,快速适应需求的变化,还可以大大提高软件的开发效率,为公司节省成本提高竞争力。文章介绍了嵌入工作流引擎的设计思想与实现方法。

关键词:工作流引擎;应用开发;Java;Hibemet;Servlet

0引言

在每个软件工程项目中,软件工程师都会面对的一个问题是:逻辑,即遵循一定规律的流程。流程可能是业务流程,也可能是生产流程。软件就是为这些流程量身定造的用于提高工作或生产效率的产物。因此在软件的开发过程中,程序员都不断地用重复的代码去塑造出这些流程,即业内人士所述的工作流。然而,在软件的维护过程中,往往由于业务或生产流程的变化,使得软件必须作出相应的修改。于是开发人员又要面临修改代码的任务。简单的流程代码倒不成问题,若碰上比较复杂的流程,则需花上较长时间去弄清楚代码的结构然后才能着手去修改,既费劲又容易出错。于是,有人便提出把整个软件流程图形化地表现出来,而且可以自定义。工作流引擎便应运而生。工作流引擎不仅解决了软件维护上的问题,而且它可以灵活地应用于不同的项目中,减少代码的编写量,从而加速软件的开发过程。例如:业务流程A->B->C->B,用工作流引擎的方法表示如图1所示。

显然用工作流引擎的方法定义流程,既逻辑清晰又形象。倘若业务逻辑需要变化,只需在工作流引擎上把流程方向线修改一下便可,免除了改动代码并且重新编译程序的麻烦。越复杂的流程越能体现它的优点。

工作流引擎既然是为开发人员而设计的,当然是嵌入到软件开发项目中的,它在整个软件中起到了大脑的作用。几乎所有相关的外围程序都由它统一管理与触发。例如图1中的ExcuteA()就是我们所说的外围程序。在实际开发的过程中,程序员只需编写外围程序然后把程序挂接到工作流引擎中适当的位置便可。就像工厂的生产线一样,不同的阶段做不同的加工。程序员只需管各阶段怎么加工,而什么时候做什么加工就交给工作流引擎去做。

1灵动的工作流引擎的设计思想

工作流引擎要求设计灵活,适应性强,才便于嵌入到各种项目中使用。图2是一个轻量级工作流引擎设计方案,系统整体架构采用三层结构。

第一层是以Java Applet嵌入Web中实现的客户端。该客户端的优点在于不需安装而实时下载到IE中使用,在应用开发中免去了由于平台更新所带来的客户端重装的麻烦。而且Java Applet在图形界面方面的技术已经日趋成熟,利用Java中的AWT与Swing组件能较好地实现流程自定义界面的功能。当然优点的背后常常隐藏着缺点,这种做法必须以牺牲客户端资源为代价。

第二层是以WebSphere为Web服务器的中间层。该层内部又分为两层,上层是Java Servlet,下层是Hibemet。JavaServlet负责与客户端的Applet通信;而Hibemet则负责Oracle数据库的数据存取操作。两者之间也进行着密切的数据交流,共同构建整个系统程序的主体。此处采用Hibemet作数据库存取的中间件还有一个重要的优点就是Hibernet能灵活地支持多种数据库类型,以持久化的思想代替数据库存储的思想。倘若在应用开发中的系统采用的不是Oracle数据库,只需对Hibernet的设置作少量改动,工作流引擎便可兼容。

第三层是Oracle数据库,负责高效的数据存取操作。

2灵动的工作流引擎的实现

2.1界面功能

界面布局分为四个区:功能按键区、树型目录区、流程元素区以及流程开发区,如图3所示。

功能按键区:包括新建、保存、删除以及退出等功能按键。树型目录区:其实就是把多个已存储的流程按树型结构显示出来。流程元素区:包含开始节点、结束节点、普通节点以及方向线等流程中的元素。可把流程元素拖到流程开发区进行流程定义。流程开发区:进行流程定义的地方。在该区域可以自由地新建和拖动流程元素。

2.2流程控制的实现

在数据库中建立三个表,分别是:

(1)节点表:用于存储流程中的节点属性。包括名字、节点权限、在定义区的位置、所属流程编号等。

(2)流向表:用于存储流程的方向线。包括出发节点、指向节点、所属流程编号、以及下面讲述到的触发函数和代谢函数。

(3)流程控制表:此表是流程控制的中心表。包括每个具体业务记录的编号、当前所在节点编号(与节点表关联)、所属流程编号。每个新业务的办理都必须先往该表插入一条新记录。通过该表的信息可以查询出当前用户所属节点有哪些待办的业务。当用户点击按钮把业务推向下一节点时,联合流程控制表与流向表便可知道下一个节点是什么。只需在程序中把流程控制表中的“当前所在节点编号”字段修改为下一个节点编号,便可实现业务跟随所定义的流程流转从而到达流程控制的目的。

2.3节点的权限

在图3所示的流程处理中,需要提供一个对节点权限设置的功能,如图4所示。

在每个节点的属性中可以设置可读写用户和只读用户权限。输入框中填入应用系统的用户登录名用“,”隔开。在开发过程中用SQL查询流程控制表和节点表便可得到当前登录用户在哪些节点,有哪些待办任务,从而形成待办业务列表提醒用户办理。

2.4外围程序调用

工作流引擎只承担软件中的大脑的作用,不实现任何的具体业务程序。为了实现工作流引擎对这些外围的业务逻辑程序的调用,需要在节点属性中添加两个属性触发函数与代谢函数。

触发函数是在用户办理业务时触发的业务程序。例如触发函数可以是一个弹出信息填写界面的程序方法,在不同节点可以调用不同的触发函数来实现该节点的业务办理。代谢函数则在用户办理完该节点的业务后,点击按钮把业务推向下一节点时执行。它可以用于例如信息的补全或其他由程序自动完成的业务逻辑。

外围程序的调用运用了Java中的接口实现方式。在工作流引擎中定义有触发函数接口和代谢函数接口(类的其中一种)。接口中分别定义一个主方法mainFunction()。所有触发函数类和代谢函数类分别实现这两个接口。类的名称填写在节点属性中的触发函数和代谢函数输入框,如图5所示。

利用Java的反射机制,工作流引擎可以自动用所填写的类名称来实例化所对应的接口,然后统一调用主方法mainFunc-tion(),从而达到触发该节点所对应的外围业务程序的目的。代码实现片断如下:

触发函数接口:

public interface TrigerFunctionInterface{

boolean mainFunction();

//定义主方法,用于触发函数与代谢函数实现

}

触发函数类:

public class BussinessLogic implements

TrigerFunctionInterface{

public boolean mainFunction(){

try{

…//业务逻辑代码

return true;

}catch(Exception e){

e printStackTrace();

return false;

工作流引擎中运用Java反射机制调用触发函数类方式:

public class Trigger{

try {

//加载触发函数类BussinessLogic

Class bussinessClass=Class.forName(“BussinessLogic”):

//实例化触发函数类BussinessLogic

Object bussinessObject=bussinessClass.newlnstance();

Ctassl]classPara=new Class[1];

classPara[0]=String.classi

//加载主方法mainFunction

java lang.reflect.Method mainFunction=bussinessClass

.getMethod(“mainFunction”,null):

//调用主方法mainFunction

mainFunction.invoke(bussinessObject,null);

}catch(Exception e){

e printStackTrace():

2.5并联流程

有时候业务流程并不是单线而是并联进行的。如图3所示,业务同时经过部门B、部门c和部门D审批,他们之间没有先后顺序。此时流程控制表需要插入三条记录分别对应于不同部门节点。所以为了兼容这并联的案例,当业务被推向下一节点时,应该把流程控制表中的原记录删除,重新插入新记录,而不只是像2.2所述的修改“当前所在节点编号”来实现。

经过三个部门同时审批后业务汇合到部门E。这里会出现两种情况:一、需要经过三个部门的审批部门E才可办理;二、只需经其中一个部门审批部门E便可办理。为了实现这两种需求,需要在节点中添加一个属性“汇合”类型,可选值“与合”和“或合”。当选择“与合”时,并联的部门之间的关系便是“与”的关系,即实现情况一的需求。当选择“或合”时,并联的部门之间的关系便是“或”的关系,即实现情况二的需求。

2.6子流程

对于复杂的流程,由于节点太多。看起来错综复杂,所以把流程分为主流程和若干个子流程是很必要的。假设部门E在办理时候也需要经部门内部几个职员才能把业务办理完。则需要在部门E的节点内定义子流程。子流程与主流程的隶属关系可以在图3中的树型目录区表现出来。

3结束语

随着国内软件业的逢勃发展,竞争越来越激烈,谁能开拓更高效率、更高质量的软件开发理念,谁就有条件在竞争中立于不败之地。而工作流引擎正是竞争者具备这种条件的重要武器。相信工作流引擎将会发展成今后的开发平台,在开发平台上拥有自己的编程语言并可灵活地调用来自不同系统的程序接口,必将把软件开发效率提升到新的高度。