netbpm工作流的架构设计及实现浅析_第1页
netbpm工作流的架构设计及实现浅析_第2页
netbpm工作流的架构设计及实现浅析_第3页
netbpm工作流的架构设计及实现浅析_第4页
netbpm工作流的架构设计及实现浅析_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

NetBPM 工作流的架构设计及实现浅析 NetBPM 组件接口 定义组件(Definition Component) 运行组件(Execution Component) 组织架构组件(Oorganization Component) 日志组件(Log Component) 任务调度组件(Scheduler Component) 管理监控组件(Admin Component) NetBpm 中的几个重要概念 flow attributes(属性) 引擎运行时上下文环境(Execution Context) 委托类 流程定义版本问题 异常处理机制 流程定义元素类图 NetBpm 中使用的框架或组件 IOC 容器Castle 数据持久层 NHibernate 示例 Web 层MonoRail 系统日志 Log4Net 单元测试工具NUnit 后记 - 读前的话:由于本文涉及内容颇多,若有地方读来不很明白,建议先跳过,整体上有个认 识后,再回过头来理解。作者认识有限,若有错误,欢迎斧正:)原文地址: NetBPM 工 作流的架构设计及实现浅析(转载请保留) NetBPM 组件接口 NetBPM 由一系列的组件构成,每一个组件都实现一个核心接口(采用 Facade Pattern) 。 不同组件各自负责的核心功能根据 WfMC 规范而来。 NetBPM 接口图: 为流程开发者提供的接口(Process Developer):该接口负责加载流程定义到 NetBpm 引擎。 首先,流程开发者依照 nPdl 创建一个流程定义,并将其打包成流程定义压缩包(该包包含 一个业务流程的所有信息) ,然后通过 NetBPM Web 界面或者是其他方式把流程定义压缩包 加载到 NetBPM 引擎,在加载过程中流程定义压缩包将会被解析被保存到 NetBPM 数据库 中。 为用户提供的接口(User ):这里用户表示执行流程的人。流程运行主要有 2 种行为:开 始一个流程和执行一个活动(activity) 。开始一个流程将创建该流程的一个流程实例,一个 流程实例对应流程定义的一次执行。一个流程实例包含了一个或多个并行的 flow-of- execution(见 flow) 。对于处在 activity-state(活动节点,见 nPdl)的 flow,系统一定会指派 一个具体的人(或者组)或者第三方来执行活动(activity) 。执行活动是 Execution Interface 的第二种行为。当然了,运转接口还会实现一些其他的方法如获取任务列表,获 取有效流程定义列表等。 外部 IT 系统(External IT Systems)和 NetBpm 引擎之间的接口:外部 IT 系统能以 2 种方式 实现和 NetBPM 的交互。 系统发起交互:系统直接和外部 IT 系统交互。当系统想要触发流程中的某一个 action 时, 它必须使用上面提到的 Execution Interface。 流程发起交互:对于流程发起交互这种类型来说,需要有 Interactors。这些 Interactors 是 流程定义的一部分,它包含在流程定义包内(实际上 Interactors 就是能够访问 FlowContext 的.NET 程序集,也就是我们后面要说到的包含委托类的程序集合) 。Interactors 在 FlowContext(FLOW 运行上下文环境)和外部 IT 系统之间建立起了通信渠道。 组织架构数据(Organisational Datastore)和 NetBpm 之间的接口:仔细想想, NetBpm 是 不是还缺了点什么,没错,那就是组织架构的信息:比如说人、团队、部门、角色等。因 为在现实情况中,对于不同的组织结构,组织架构信息可能被保存在不同类型的数据库中, 如 LDAP 系统,关系型数据库等。为了让 NetBPM 能够在一个现实的组织架构中实现快速部 署,NetBPM 把所有的组织架构信息都聚集在一个组件(Organisation Component)中。这 种做法也就是我们通常说道会话门面模式(Session Faade Pattern) ,它使得 NetBPM 访问 来自不同数据源的组织架构信息变得更为简单。 下面我们逐步介绍 NetBPM 的各个组件,下面是 NetBpm 组件结构图: 定义组件(Definition Component) 该组件实现核心接口 IDefinitionSessionLocal,用来解析、加载流程定义压缩包,并将 其保存到数据库中。此外,它还提供获取某个流程定义,获取所有有效流程定义列表等和 流程定义相关的方法。 运转组件(Execution Component) 该组件实现了核心接口 IExecutionSessionLocal,它是 NetBPM 引擎推动核心,如前面 如述,它主要实现 2 个方法:开始一个流程实例( Start ProcessInstance)和执行一个活动 (Perform Activity) 。另外,它还提供获取用户任务列表,取消流程实例等辅助流程运转的方 法。 组织架构组件(Organization Component) 该组件实现接口 IOrganisationSessionLocal,它把所有的组织架构信息都聚集在一起, 包括 Users、Groups 和 Memberships。运转组件在为 activitie-state 指定执行者时,需要有 关 user 和 group 的信息。这些信息将以只读模式由组织架构组件向运转组件提供。下面是 NetBPM 默认的组织架构组织数据模型。在此基础上,我们可以很方便的实现自定义的适 合实际项目需求的组织架构组件,以和我们的用户数据库或者是 LDAP 系统相关联。 NOTE:NetBPM 源码中实现的只是一个简单的组织架构模型,但它提供了一种思考方 向,我们可以很方便在此基础上进行扩展来实现满足切实需求的自定义组织架构组件:) 日志组件(Log Component) 该组件实现接口 ILogSessionLocal,用来记录工作流引擎的操作痕迹,象属性值的更新 (如用户提交的表单被上级打回重新填写,那么就会出现多次表单数据,这就是一种属性 更新) ,委托类的调用情况等都会被记录下来保存到数据库中。 任务调度组件(scheduler component) 该组件实现接口 ISchedulerSessionLocal,在现实的业务流程中,我们经常会遇到需要 定时触发某个任务的需求,任务调度组件正是作用于此。引擎或者是第三方把需要在某个 时刻执行的任务信息(包括任务执行环境、执行时间等)封装成 Job 保存到数据库中。任 务调度组件将按照指定的时间间隔不停的扫描任务表,根据执行时间对比来执行定时到了 的 Job。 管理监控组件(Admin Component) 该组件用来对流程定义,流程实例执行情况等进行监控。 (源码待完善)下面是 NetBpm 核心项目在 Visual 该组件用来对流程定义,流程实例执行情况等进行监控。 (源码 待完善) 下面是 NetBPM 核心项目在 Visual Studio 解决方案中的源码结构图,所有组件都包含在 Workflow 文件夹下,每一个文件夹分别对应实现了一个核心组件。 - NetBpm 中的几个重要概念 flow flow 不知道翻译为什么好,在 JBPM 中叫做 Token,翻译为令牌,这里我们就叫做 flow 吧。它代表 activity-states(活动节点,见 nPdl)的一个 “thread of execution”,相当于 是一次流程实例执行过程中在流程定义模板中的令牌(还真难描述清楚,看下面一起理解: ) ) 。前面说了,一个流程实例代表一个流程定义的一次执行。如下图所示,流程实例的状 态可以看成是一颗 flows 树。 当开始一个流程实例后,在 start-state(开始节点,见 nPdl,start-state 实际上可以看 做是一种特殊的 activity-state)引擎将自动产生一个名为 root 的 flow。flow 中包含了该流程 实例的相关信息,如属性值、流程定义信息、flow 所在 activity-state 的执行者等。root flow 在遇到 fork(分散节点,见 nPdl)之前,将更新其带有的实时信息(如执行者、属性值等) , 这些实时信息随着流程的运转而变化。遇到 fork 后,根据 ForkHandler 委托类,root flow 将分散成若干(1 个)forked flow(我们可以把 root flow 称为这些 forked flow 的父 flow) 。 若是分散为多个,则此时 forked flow 将并行运行,父 flow 则暂时退隐,只至到 join(汇聚 节点, 见 nPdl)汇聚,引擎将根据 join 定义的 JoinHandler 委托类来确定激活父 flow 的机制。 NOTE:关于 fork 和 join 机制,请参考 nPdl fork、join 小节一起理解。 attributes(属性) attribute 用来表示流程实例中的变量。一个 attribute-instance(属性实例,也就是属性 值)代表一次流程实例执行过程中对应属性的实例。属性一般有几种,一种是 activity- state(包括 start-state)需要用户或者第三方来填写(更新)的属性(一般对应用户 Web 界面表单上要填写的值) ,一种是角色对应的属性,还有一些用作标识属性(用来存储某些 信息以方便后面的节点运用这些信息处理逻辑判断) 。 serializer(属性的序列化) : Serializer 和 HtmlFormatter 都是委托类,Serializer 负责把属性实例在 .NET-Objects 和文本两 种状态间进行转换,以方便把属性值存入和取出数据库。而 Htmlformatter 主要用来联系属 性值和 Web Forms 显示时对应的 http-text。 attribute 的范围:attribute-instances(属性实例)和 flow 有关。在 process-definition(流程定 义根节点,见 nPdl)节点中定义的 attribute 和 root-flow 关联,而在 concurrnet-block(并行运 行块,见 nPdl)中定义的局部 attribute 实例则和 forked flow 关联。一个 flow 能够“看见” 和它关联的所有属性以及该 flow 的父 flow 的所有属性。 引擎运行时上下文环境(Execution Context) 因为图片太大,关于继承 IHandlerContext 的接口关系图查看点击这里 ExecutionContext(ExecutionContextImpl 类型的对象,我们暂且翻译为运行时上下文 环境:) ) 包含了引擎在运行时和流程实例相关的所有有用信息(上文中提到的 flowcontext 就是一种 ExecutionContext) ,它在委托类(包括流程定义压缩包中程序集中定 义的委托类)和流程引擎之间建立起了相互联系的渠道,这是非常关键的。如上面 ExectutionContext 类图所示,ExecutionContextImpl 实现了下面这些接口: IAssignmentContext、IDecisionContext 、IForkContext、IActionContext、IJoinContext 、IProces sInvocationContext、ITaskContext,这些接口都是为匹配特定的委托类而设计,它们规范了 一种特定的上下文环境,如 IActionContext 匹配 action 类型委托类,IDecisionContext 匹配 DecisionHandler 类型委托类等,而 ExectutionContext 是所有这些特殊的运行时上下文环境 的一个综合。当引擎在运转组件把 ExectutionContext 作为参数传送到具体类型的委托类时 (关键:这就是委托类和流程引擎建立联系的方式) ,ExecutionContext 对象将“拆箱”成 为特殊的 Context,如:把 ExecutionContext 对象传给 action 类型的委托类 Run()方法时, ExecutionContext 对象将拆箱为 ActionContext 对象以限制其能够调用的方法。 如“继承自 IHandlerContext 的接口”图中所示,这些接口都继承了同一个接口 IHandlerContext。IHandlerContext 是一个规范了最基本的委托类处理上下文环境的接口, 实现该接口的继承几口也就都要实现 IHandlerContext 中定义的方法,当然每一种继承它的 特定接口又都可以具有其特定的方法。我们先看公共接口 IHanlderContext 类图:如上 IHandlerContext 接口图所示,这些接口都继承了同一个接口 IHandlerContext。IHandlerContext 是一个规范了最基本的委托类处理上下文环境的接口, 实现该接口继承接口的类也就都实现了 IHandlerContext 中定义的方法。当然,每一种继承 它的特定接口又都可以具有其特定的方法。我们先看公共接口 IHanlderContext 类图: 大多数的方法,我们从方法名称就可以看出其具体作用了,这里重点介绍下 GetAttribute()方法和 GetConfiguration()方法,这是我们在写委托类实现时,要经常用 到的 2 个方法。GetAttribute()用来获取流程实例中的属性值,包括流程前面处理者产生 的属性值(如用户填写表单的值)和前面处理引擎事件中设置的表示属性值(注: IActionHandler 具有 SetAttribute()方法,该方法经常用来标识属性值,供后面程序逻辑 用)等。而 GetConfiguration()用来获取流程定义中设置的 parameter(参数,请 nPdlparameter 小节) 。 下面再来看几种典型的特定上下文环境接口: IAssignmentContext:为 IAssignmentHandler 委托类提供引擎上下文环境,该接口定义了获 取组织架构信息的方法,具体实现方法见类图。 IActionContext:为 action 提供引擎上下文环境,注意其具有 SetAttribute 的方法,可以为 流程实例中的属性赋值,具体实现方法见类图。 IForkContext:为 IForkHandler 委托类提供引擎上下文环境,它定义了如何从父 flow 分散 forked flow 的方法,见类图。 IJoinContext:为 IJoinHandler 委托类提供引擎上下文环境,它定义了获取其他并行 flows 的 方法,见类图。 IProcessInvocationContext: 为 IProcessInvocationHandler 委托提供引擎上下文环境,实现方 法见类图。 其他的委托类型上下文环境除了实现基本 IHandlerContext 方法外,没有特定的方法,请参 考 IHandlerContext 方法。 委托类 在前面我们一直提到委托类,那么委托类到底是什么呢?这里委托的概念指的不是. NET Framework 中 delegate,这里可以理解它为“委托、代为处理”这样的概念就好。 NetBPM 被设计成通用的流程处理引擎,NetBPM 核心执行引擎只负责处理最基本的 业务流程逻辑,所有不定的逻辑都被委托给一系列的接口,这些接口称作 Delegation Interfaces(委托接口) ,而实现这些接口的类就是委托类。流程定义约定在什么场合使用 什么委托类型,引擎和委托类如何关联也在流程定义中完成。 为了达到最大的可扩展性,流程开发者在流程定义时可以选择下面任意一种委托类实 现方式: 使用已经在 NetBpm 引擎中实现的有效的委托类。 (具有通用性的委托建议采用这种方式在 引擎中定义,以便重用) 使用自定义的委托类,以.NET 程序集的形式通过流程定义压缩包动态加载。 正是方式 2 这种形式给 NetBPM 带来了极大的灵活性,把只适合于某个特定流程的的 程序逻辑(这些往往占了大多数)以.NET 程序集的形式定义在流程定义压缩包中,NetBpm 通过流程定义组件将其解析并保存至数据库。当引擎运转流程需要调用委托类时,引擎利 用反射技术实例化出委托类对象,然后利用上文介绍的运行时上下时环境 (ExecutionContext)建立起委托类和引擎之间的交互渠道,这真是一个令人兴奋的设计: ) 下面是 NetBpm 中的委托类型(建议和 ExecutionContext 一节一起理解): AssignmentHandler: 实现接口 IAssignmentHandler, 它可以和组织架构中的 IT-System 相互通信,用来为 activty-state 指定执行者。 IAssignmentHandler 具有唯一的方法 SelectActor(IAssignmentContext assignerContext),其中的 assignerContext 是其和引擎联系的 渠道; ActionHandler:实现接口 IActionHandler,它用来执行一段流程引擎外完成的程序逻辑,关 于 action 在哪里执行,什么时候执行等在流程定义中被定义。actions 可以被看作一系列流 程执行事件的侦听接口,它具有方法 Run(IActionContext actionContext),actionContext 是它 和引擎联系的渠道。 DecisionHandler:实现接口 IDecisionHandler,它用来选择决定走哪一条 transition(边, 见 nPdl) ,具有方法 Decide(IDecisionContext decisionContext),该方法返回选择要走的边的名 称,decisionContext 是其和引擎联系的渠道。 ForkHandler:实现接口 IForkHandler,当执行到 fork 节点时, Forkhandler 用来决定从 fork 流程的边中哪些边需要“forking” 。它具有方法 Fork(IForkContext forkContext),forkContext 是其和引擎联系的渠道。注:forkhandler 可以在同一条边上分散多个 forked flow。 JoinHandler:实现接口 IJoinHandler,当执行到 join 时,JoinHandler 决定是否要激活父 flow,它具有方法 Join(IJoinContext joinContext),joinContext 是其和引擎联系的渠道。 Serializer:实现接口 ISerializer,具有方法 Serialize(Object valueObject)和 Deserialize(String text),该委托接口负责用来转换属性值,把属性值在.NET-objects (.NET 对象)和 text- format(文本) 之间转换。其中,text-format(文本)用来存储属性值到数据库中。 HtmlFormatter:实现接口 IHtmlFormatter,该委托主要用来在属性值和其相对应的 web 界 面元素之间建立联系,同时负责解析 web 界面元素具有的值。若移植到 ASP.NET 平台,该 接口建议重写。 ProcessInvocationHandler:实现接口 IProcessInvocationHandler,该委托实现收集子流程的 初始化数据、收集处理结果、指定完成子流程后要流入的边等方法, processInvocationContext 是其和引擎联系的渠道。 /.是否要添加委托类的例子 - 流程定义版本问题 流程定义的名称与版本 包含在一个流程定义压缩包中的信息叫做流程定义。NetBpm 中,流程是由字段 name 来区分的,也就是说引擎根据流程的 name 来判断两个流程是否相等。在流程定义包 中不能指定版本,当一个流程定义被引擎加载后,NetBpm 将检查是否有该流程定义的旧 版本。如果有,NetBpm 将自动设置该新加载进来的流程版本为所有存在的旧版本流程定 义中最高版本数目基础上加 1。 流程执行与版本 当调用运转组件获取流程定义列表方法时,只能获取到每个流程的最高版本流程定义。 这样做保证了用户总是从最新版本的流程定义开始一个流程实例。当新的流程版本加载到 NetBpm 时,所有正在运行的旧版本的流程实例将保持在原来流程定义方式下运行。 委托类与版本 关于版本的另外一个方面是委托类。不同版本流程定义的委托类不是共享的,也就是 说每个流程在执行时只会“看到”它自己流程定义的委托类。 - 异常处理机制 NetBpm 作为一个集成平台,当流程运行时,肯定会依赖公司很多其他的 IT 资源,一 旦这些依赖导致流程执行时出现错误,NetBpm 提供了 3 种解决机制: 忽略错误 把错误日志记录下来(默认采用的机制) 错误执行回滚操作(rollback) 执行回滚机制中,流程实例将会被回滚到执行 activity 之前的状态。如果是对 NetBpm 调用 Eecution Interface 时发生流程错误,所有的流过的 transition(边)都会执行回滚。 - 流程定义元素类图 关于流程定义的详细情况,参见 nPdl。 - NetBpm 中使用的框架或组件 NetBpm 中用到的框架、组件、工具比较多,它们大都是优秀的开源项目。如 Castle,NHibernate,Log4Net, NVelocity,NUnit,NAnt 等,不要被这些框架吓倒,实际上, 它们仅仅只是“框架”而已:) IOC 容器Castle NetBpm 使用了 Castle 框架,主要用它来实现 IOC(控制反转或者说依赖注入) ,以依 赖注入的方式加载核心组件,如 DBClassLoader,流程定义组件,运行组件,日志组件,组 织架构组件,任务调度组件等。在 Web 程序启动的时候,根据配置文件,所有的核心组件 都将注册到 Caslte IOC 容器中,以后当需要使用某个组件的时候,只需利用系统提供的 ServiceLocator(服务加载工具类)从容器中获取实例即可。另外,在任务调度组件中也有 用到 Castle 的 Startable Facility(注:大家把 facility 理解为注入性质的,对 Castle IOC 内核 容器的功能扩充组件。Castle 本身自带实现了一些 faciltiy,开发者也可以自定义 facility), 该 facitlity 主要用来自动运行程序(这里用来自动间隔扫描任务表,进行任务调度) 。 Castle 是.NET 平台下一个功能强大的优秀开源框架,关于 Castle 的更多信息,请看 Castle 官方网站。另外 TerryLee 的博客中关于 Castle 的中文资源也很丰富。 数据持久层 NHibernate NetBpm 中 NHibernate 组件是作为 Castle 的一个 facility 存在的,它用来实现 NetBpm 数据持久层, 并方便的实现了事务支持。关于 NHibernate 的更多信息,请看 NHibe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论