activiti和jbpmactiviti工作流实例引擎哪个比较好

j2ee常用工作流比较(shart、osworkflow、jbpm)
基于一个小的工作流引擎在构建一个BS的领域应用框架,应该是java的
我觉得选用jbmp是一个比较好的选择。
Shark(Enhydra
Osworkflow opensymphony
Jbpm(JBoss JBPM)
工作流描述语言
1、XPDL:WfMC制定的描述业务流程控制流的XML格式规范,格式复杂,与具体语言无关,不灵活
1、XML:流程定义格式简单,使用灵活
2、基于有限状态机模型
1、JPdl:JBoss jBPM Process
definition language,一个商务流程被看作是一个UML状态图。
2、基于UML的状态图和活动图来定义流程,已加入JBOSS大家庭,市场前景看好。
是否开源,开源协议
一个可扩展的工作流引擎框架。现在不再开源,用于商业用途
开源的嵌入式工作流引擎 ,它的使用遵循 Apache License
一种基于J2EE的轻量级工作流管理系统,它的使用遵循 Apache License
相关开源项目
Osworkflow for
支持是否全面
流程定制工具JAWE
1、带有一个简陋的流程定制工具,但十分简陋且常有错误
2、需要专业技术用户使用
1、Jbpm3的图形化流程定义嵌入到jboss
eclipse IDE
2、流程定制方式更接近用户的理解
体系和功能最为复杂,秉承“模块化”的思想,比较容易扩展
有良好的扩展性,绝对的灵活(同时也增加了开发者的工作量,需要自己写一些必要的函数)
最适宜扩展(Jbpm的过程模式支持是比较固定的,但是其对任务的中action扩展是很的灵活)最适宜被商业化应用
1、Shark的持久层采用DODS来实现
1、它提供的持久化API:EJB,Hibernate,JDBC等
2、OSWorkflow可以与Spring集成。
1、利用hibernate持久化
备注:shark 和 jbpm
都强迫你使用它的用户模型,怎样把企业现有的用户模型(包括组织结构)映射过来是很繁琐的事情
Shark, OsworkFlow ,
&&&&Shark是体系和功能最为复杂的代表。它是一款遵循WfMC的XPDL标准开源工作流引擎,并且同时遵循OMG组织的Workflow
Management Facility规范。XPDL的两个最重要的概念是Process和Activity。XPDL中的Activity是基于UML1.x中的活动图的概念。活动图天生的适于工作流程建模,它相对于状态图的一个最大的优点是容易做并发线程的分叉控制,这些并发线程可以同时执行也可以顺序执行;它还有一个优点是有泳道的概念,可以控制工作流引擎中的任务的产生。
&&&&在所有开源工作流引擎中,Shark的体系最为完备和复杂。其一直秉承着“模块化”的思想,所以比较容易扩展。但是自从被Together公司收购后,Shark的商业化色彩已经越来越浓,改称为Together Workflow Server,并仅以Community Edition的形式提供了部分开源代码供参考。
&&&&OSWorkflow
&&&&OSWorkflow是最轻量型的代表,也是一款非常灵活和低级别定位的工作流引擎的实现框架。低级别定位的意思是说,它不是定位在解决流程模型对象和运转场景,而是提供一套可维护调度的机制,供开发人员自主扩展。这个维护流程调度机制OSWorkflow选择的是基于行为(Action)的FSM理论,所以OSWorkflow更像是一个复杂而灵活的有限状态调度机。
&&&&Osworkflow有个重要概念是State,State是由step和status联合表达的,一个State就是一个step中的某个status;而state的转换由action来驱动,类似状态图中的event,因为一个event对应一个action
&&&&OSWorkflow在国内项目应用得较多,很多国内的简易审批流程项目都是基于其引擎二次开发而来。这主要是由于OSWorkflow是基于Action驱动的,而国内的客户也很容易接受这样的操作习惯。但OSWorkflow所依赖的FSM模型对于分支、聚合、子流程的支持度很低,这一点在实施过程中需要注意。
&&&&Jbpm结合应用了状态图+活动图+PetriNet的知识,而且这里的活动图还是UML2.0版的。UML2.0的活动图中,节点不叫活动(Activity)而叫动作(action),活动成了一个高层次的概念,它包含一个动作序列。一个活动图展现一系列的动作,这些动作组成了活动。Jbpm把action也改名了,称为state。Jbpm使用的状态图的概念有transition/event等。Jbpm来内部实现中还采用了PetriNet的概念,如token,signal等,jBpm对Token的应用很有特色,巧妙地利用Parent-Child Token的机制处理分支、父子流程等复杂应用场景。
&&&&jBpm是最适合扩展的代表,是在所有开源引擎中最适宜被商业化应用的一款。首先其流程建模模型是基于Activity Diagram(活动图)的,并在引擎构建上融入了FSM和PetriNet思想,所以其内核和根基比较牢固扎实。其次,自从被JBoss收购后,其3.
x系列的结构更加趋于微内核,Plug-in思想也更加深入。其同时还提供了对BPEL扩展,存储支持JBoss
Hibernate实现,集成了JBoss seam,规则引擎准备采用JBoss
rules,并准备集成JBoss Messaging。这样,不论从内核和外围应用,jBpm都具有了强劲的动力。
市场预测&&&
&&&&Jbpm3将在3月发布阿尔发版,jbpm3的最终版将支持bpel4ws的核心部分。所以,据估计Shark将在引领风骚数百天后,被jbpm3赶下第一宝座。但bpel4ws暂时不会和我们亲密接触了,估计在今年它是不会真正走进我们的生活的。
Framework3中是不是也加了工作流支持?
(个人感觉
WWF的流程定制方式接近于 程序设计流程,像一步步的写程序)
下面是有关的调研报告:
&&&.net framework3中加入了WWF(Windows Workflow
Foundation),是帮助你在Windows平台上快速建立工作流应用程序的编程模型、引擎和工具,它为开发和执行各种基于工作流的应用程序提供了编程框架和工具。
&&&Windows Workflow Foundation是一个帮助你开发基于Windows平台的工作流解决方案的可扩展的框架,允许你在.NET应用程序中嵌入工作流。WWF本身不是一个可执行的软件或程序,WWF主要是帮助你创建自己的工作流应用程序。作为将来Microsoft WinFX的一部分,WWF提供一组API和工具以支持基于工作流的应用程序的开发和执行。WWF为创建跨越不同应用程序的端到端解决方法提供了一个简单、统一的模型。
&&&Windows Workflow Foundation是一个通用的工作流框架。基于WWF的解决方案由相互链接的.NET组件构成并运行在宿主程序中。就像你在一个特定的设计环境下创建ASP.NET页面一样,WWF也为你提供了一个良好的设计环境,在可视化设计器中,你可以创建特定的流程、在工作流组件中增加代码、定义商业过程,WWF提供了工作流引擎、.NET-managed
API、运行时服务、与Visual Studio 2005集成的可视化编辑器和调试工具。你可以使用Windows Workflow Foundation创建和执行运行在客户端和服务器端的工作流,并且可以运行在所有的.NET应用程序中。
Windows Workflow
Foundation:支持基于工作流的应用程序
&&&&&&工作流是一个简单思路:按照特定顺序执行的一系列步骤。采用工作流技术后,逻辑与普通代码不会纠缠在一起,过程中的每一步骤都会明确定义,然后由工作流引擎执行。这样做的结果就是,过程执行清楚明确。
&&&但是,提供通用的工作流技术之路却是困难重重。举例来说,如何使用一种方法来满足不同工作流应用程序的各种要求?WF 给出的答案是,从全局视角来看待工作流。WF 工作流只是一组由 WF 引擎执行的活动。一个活动就是一个类,它可以包含工作流创建者认为有必要的任何工作。活动可以在不同的工作流中重复使用,因此,在针对新问题创建自动化的解决方案时,过程将会更加容易。
&&&提供通用工作流技术面临另一个困难是,面向人员工作流和面向系统工作流的传统分歧。通常来说,工作人员使用的工作流应用程序需要有较高的灵活性,能够进行实时更改。而一般由系统,也就是由软件使用的工作流应用程序则相对更加静态,但要求尽可能高效。WF 综合考虑了这两种不同的使用情况,不仅包括面向人员的功能(如更改运行中工作流的功能),同时还支持更多面向系统的操作。
&&&通过 WF 的
Windows 通用工作流技术,.NET
Framework 3.0 为广大开发人员提供了一种非常有用的软件开发模式。随着面向流程的软件继续风行,工作流技术也会随之推广。
WWF的应用场景
&&&WWF本身并不是一个业务平台,它只是为开发人员提供创建工作流软件的一个平台,也就是说WWF不是工作流应用平台,而是一个开发工作流应用的平台。使用这个开发平台可以开发具有以下特点的工作流平台
业务流程辅助办公软件
&&&不同行业者有各自独立的业务流程,使用一些业务流程管理软件可以提高流程效率并降低出错率,比如审批类、办公类、采购类、MSI、电子商务、电子政务、电子法务、以及需要按一定的业务流程办公的所有领域的办公辅助系统中都可以使用工作流
软体内部工作的顺控制
&&&很多时候,在不涉及业务的情况下,对软件的自身协调控制也有很复杂的流程,比如一个需要设置很多参数的软件安装向导、一个窗体内各控件间复杂的锁定关系、一个软件中多个窗体相互调用的顺序都可以用工作流实现
自动筛选查询类系统
&&&比如招投标系统中的自动开标模块、考生录取系统中的自动投档模块、搜索引擎的自动分析模块,可以使用工作流管理这些模块的运算方案与运算路径
自动化控制中
&&&在工控系统中,有时需要控一个的顺序对一系列的机器进行控制,可以使用工作流管理这些控制
有状态的、持久化的、不间断运行的应用程序
&&&WWF简化了创造有状态的,不间断运行的异步工作流应用程序的过程。WWF运行时引擎管理工作流的运行,为工作流的长期运行提供保障,并能抵抗机器的重启。WWF运行时服务提供了一系列的附加功能,例如WWF服务为能温和且正确的处理错误提供了事务和持久化。
工作流模型
&&&WWF为开发人员提供了一个工作流模型,来描述应用程序所需要的处理过程。通过使用工作流模型所提供的流程控件、状态管理、事务和同步器,开发人员可以分离应用程序逻辑和业务逻辑,构造一个高层次的抽象,达到提高开发者效率的目的。
组件的重用
&&&WWF为开发者提供了一系列的活动——活动是一种包含了工作单元的可配置逻辑结构。这种结构封装了开发者可能经常性用到的一些部件,这样就节省了开发者的时间。如果遇到一些特殊的需求或场景,WWF同样为开发自定义的活动提供了简单的方法。通过将工作流引擎载入进程,WWF可以使任何应用程序和服务容器运行工作流。
&&&运行时服务组件被设计成可插件形式的,这个可使应用程序以最合适的方式来提供它们的服务。WWF还提供了一组运行时服务的默认实现,这些服务能满足大部分类型的应用程序。
&&&另外,WWF还提供了对ASP.NET的out-of-the-box支持,让构造和运行能在IIS和ASP.NET环境的工作流变得简单。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Activiti进行时——企业工作流生命周期贯通 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了36633字,被21人关注,获得了29个喜欢
Activiti进行时——企业工作流生命周期贯通
图1:一个典型的审批工作流程
最近做了一次对企业/云平台级工作流引擎Activiti的调查:
TA,系出名门——由JBoss公司jBPM4引擎的原作者创立(JBoss公司无奈地已在jBPM5中改用了Drools内核、走了其他路线);
TA,植根于Java开源社区,拥有SpringSource、MuleSoft、Signavio等公司以及全球大量拥护者基于最新开发实践的养分支持;
TA,“出场费”要比IBM、Oracle等大厂的同类低很多,却同样支持BPMN 2.0国际标准、各大流行数据库、集群扩展等,包括对云平台所需的多租户特性也已有原生支持。
InfoQ上2012年4月就已有过,本文则是笔者近2个月实战Activiti的一篇简书&共享。
目标 ------------------------------------
用户能方便地修改流程定义的细节(例如改分歧条件、复制添加已有的类似节点),只要不涉及新的表单/服务/编程、就无需委托开发人员出马。
能以REST服务方式调用,与现有业务系统衔接。比如这次的业务系统是.Net架构,而Activiti则是Java开源引擎,但因为提供了REST API接口(且易于扩展)、能以JSON/XML方式完成轻便的数据交互。
支持BPMN 2.0国际标准(具体后述)。标准统一之争虽然往往夹杂着企业各自的便利/利益,但毕竟有其行业合理性与权威性(例如繁杂的医疗/金融/物流领域),在行业出现新的需求而升级标准时、只需升级符合新标准的引擎就能适应需求。
成果 ------------------------------------
打通基于REST API接口的 工作流生命周期(不足部分做定制补充)
流程设计模型:一览、编辑(有模型编辑器)、部署(+允许启动者)--&流程定义
流程定义:一览、挂起/激活、启动--&流程实例
流程实例:一览、挂起/激活、查看(当前状态)
任务:一览(我的任务)、签收/完成(表单变量--&流程变量)
监听器:触发、处理(e.g.发送任务通知邮件)
表单编辑器:Activiti并不带表单编辑器(),内置+外置两种表单支持方式能满足入门级业务需求,但多数需集成开发。
邮件模板编辑器:邮件模板的可视化编辑、也不在工作流引擎的负责范围之内,需根据业务需求定制开发。
资料 ------------------------------------
调研、定制中以下一些资料较为有用,(感谢相关作者&)已有相关基础的读者可据此推断本文的参考价值。
官方文档(含REST API):汉化文档:
中文社区::咖啡兔:
引擎应用项目范例: 官方:,
开发环境构筑:
引擎源码:引擎类库API:
工作流概念+BPMN标准
如果希望直接将Demo跑起来边看边理解的话,可以跳到,否则就先随我把概念部分混个眼熟。
工作流概念
制作了一张工作流在生命周期中不同阶段/环节间切换的关系图:
图2:工作流生命周期
REST API:在此特指Activiti引擎的RESTful接口、以及另行扩展的接口,提供所有工作流解析/处理的核心功能
模型编辑器:在此特指Activiti Modeler,也可选用其他来做定制
流程设计模型:工作流在此处于设计环节,可被可视化地编辑调整(如图1)。其中重要的元素,包括用户任务(与表单画面衔接,接受用户的选择/承认/否决之类的输入;是活动节点中最主要的一种,参见)、监听器(响应各种任务/活动节点上的事件(e.g.已被签收/已被办理)、进行不同处理(e.g.按照特定模板发送通知邮件))。
流程定义:工作流在此处于“已部署”环节,以一个“请假流程”为例的话、一旦被部署、有权限的用户就可以启动/发起该流程申请请假了(诞生一个“流程实例”、见后),流程定义的内容已不可被编辑(只可被挂起/激活),如需做修改、只能对流程设计模型做编辑、并再次部署。换句话说,流程定义、是处于流程从设计环节到运行阶段之间、相对稳定的中间环节。
流程实例:工作流至此已进入“运行中”阶段。一个已经被启动、进入“运行中”阶段的工作流,就好比一个“状态机”,可能处在不同活动节点的不同状态上(还可能并发)、直至结束。当工作流运行到一个用户任务节点(比如“总经理/副总经理承认”)、而该任务的候选办理者有多人时,其中之一(比如副总经理)就可以“签收”,然后“办理”该任务(也可以在界面上隐匿“签收”、一律只显示成“办理”)。
流程状态跟踪器:对“运行中”阶段的工作流当前所处的活动节点、状态做出可视化标识。使用官方组件Diagram Viewer会很方便,也可使用。
历史流程实例:已经结束的流程,仍可被查询到(包括其中的用户任务、选项输入),这会有助于事后分析统计。注意:5.16版本开始还新增了“事件日志机制”,可采用大数据存储分析(参见)。
BPMN 2.0标准
先上一张诺贝尔颁奖盛典筹备工作的设计模型图:
图3:The Nobel Prize Process Diagram
基于工业标准的工作流设计,是满足不同领域客户复杂业务需求的有力保障。
BPMN2.0标准工作流的模型编辑与保存,可以在浏览器App形式的Activiti Modeler中进行(并可以嵌入你的业务系统中),在此直接对照着Modeler的图标对主要的BPMN元素做简单介绍:
图4:Activiti Modeler Shape Repository -- BPMN2.0
开始事件(Start Event)&提醒&
启动者变量(initiator):一个开始事件的initiator属性中所保存的、只是一个“用于记录启动者user_id的变量名称”,可以算是个“变量声明”属性。当一个用户、例如"kermit"(官方范例用户)、启动了这一工作流时(在流程设计模型被部署、成为一个“流程定义”后、它就能被某一用户启动成为一个“流程实例”),"kermit"就会被记录到在initiator中声明的变量、比如"starter"中,那样就会有一个流程变量starter被赋值为"kermit",并能在后续的活动节点中(e.g.用户任务)被用于任务办理人(assignee)属性的赋值表达式(e.g.${starter})、或是其他的例如分歧条件表达式中(${starter=="kermit"})。详见。开始事件的initiator属性是唯一用于保存“变量名称”的,在整个流程级别、或是任务级别、都存在着类似于candidateUsers/candidateStarterUsers的属性,它们保存的直接就是允许启动流程/办理任务的用户ID(允许多个)。详见。注意:Activiti Modeler的当前版本还不支持设置流程级别的candidateStarterUsers/candidateStarterGroups(允许启动者),Eclipse插件Activiti Designer中可以,但仅供开发者使用;因此需要通过扩展REST API、在“流程设计模型::部署”、或是“流程定义::设置”环节进行设置。
活动节点(Activity)&提醒&
用语:Activity通常被翻译成“节点”、包括了各种任务(Task)、顺序流(Sequence Flow)、子流程(Sub-Process)等,一切具备生命周期状态的元素。国内也有使用“步骤”(Step)的,但其实Step的定义似乎应是“节点(Activity)+网关(Gateway)”(@)。
humanPerformer vs activiti:candidateUsers:这里将引入BPMN标准属性与Activiti扩展属性的对比与互换的话题。1.语法上的不同:Activiti扩展确有其化繁为简的优势,请比较两段定义("activiti:"打头的即为扩展),a. BPMN标准属性&process&
&userTask id='theTask' name='important task' &
&potentialOwner&
&resourceAssignmentExpression&
&formalExpression&user(kermit), group(management)&/formalExpression&
&/resourceAssignmentExpression&
&/potentialOwner&
&/userTask&
&/process&
b. Activiti扩展属性&process&
&userTask id="theTask1" name="my task" activiti:assignee="kermit" /&
&userTask id="theTask2" name="my task" activiti:candidateUsers="kermit, gonzo" /&
&userTask id="theTask3" name="my task" activiti:candidateGroups="management, accountancy" /&
&/process&
2.标准与扩展冲突的解决:详见a.Activiti扩展的前提是:总有简单的方法、转换成标准方法b.Activiti扩展的目标是:最终把它们加入到下一版本的BPMN规范中, 或者至少可以引起对特定BPMN结构的讨论
结构(Structural)&非重点&
网关(Gateway)&非重点&
结束事件(End Event)&非重点&
连接(Connecting Object)
顺序流(sequence flow):用于连接各种事件、活动节点、网关的连线。除了网关会对流出的顺序流有特殊限制之外(例如排他网关)、BPMN缺省的流出顺序流(若有复数个的话)是“并发”的、即同时发出。可以对顺序流做条件式限制,即添加一个conditionExpression元素:&sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask"&
&conditionExpression xsi:type="tFormalExpression"&
&![CDATA[${order.price & 100 && order.price & 250}]]&
&/conditionExpression&
&/sequenceFlow&
注意:目前条件表达式只能使用UEL(统一表达式语言),详见。
开发环境构筑:Eclipse + Maven + Tomcat + Activiti
我所使用的开发环境:
Eclipse Java EE IDE for Web Developers, Luna
Apache Maven 3.2.3
Apache Tomcat 7
Activiti 5.16.3(5.16.4起设置方法有变化且官方文档未同步更新):请下载,而非其运行版
Maven的基本配置对初学者来说会多有挫折Maven本身是个好东西,开源项目很多对其他开源项目有大量的依赖引用,难免存在交叉引用、版本覆盖、重复下载等繁琐问题,而Maven工具&标准就是为了应对这个而产生的(并成为Apache顶级项目)。可是,主要陷阱在于:
国内糟糕的网络访问情况...很多中央仓库镜像会出现超时
部分依赖库会不存在于中央仓库中,需手动下载后放入本地仓库中
Maven可以用命令行方式运行、也可用Eclipse插件方式来使用,但有时两者的结果会不尽相同...
解决方法:
找到好文档,从新建/导入一个Maven项目、编译&运行它开始 注意: 其中有些章节为【必须读】有些【不必读】 2.Maven的安装和配置 2.2.配置 2.2.1.修改默认的本地仓库位置:必须读 重新设置本地仓库位置,使得你可以更方便地 a.将需要手动下载的依赖库放置其中 b.备份已经成功构建的本地仓库、用于环境移植 2.2.2.修改默认的中央仓库镜像:不必读 通常是根据项目不同,修改项目pom.xml文件中的&repository&配置 4.使用Maven来构建Web项目 4.1.创建Maven的web项目:不必读 我们需要的是导入Activiti官方项目、而非新建,具体方法见后。 4.2.使用Maven添加项目依赖包:不必读 导入项目的pom.xml中已经配置好了,除非你有新的依赖包需求。
使用国内经验者已有的“私服”:比如,具体POM设置见后。
小组开发时,可考虑在局域网里搭一个“私服”(自己的中央仓库):参考。
导入已有项目:\modules\activiti-webapp-explorer2项目
Eclipse中导入的方法:File & Import... & Maven::Existing Maven Projects & Next & 选中项目根目录下的pom.xml文件即可。
Maven配置修改(pom.xml文件编辑):m2eclipse插件已经装好的情况下,pom.xml会自动被在表单编辑器中打开(不过通常只需在文本方式下编辑、表单方式下辅助阅读)a. 添加中央仓库镜像,比如咖啡兔的Maven私服(不过有时也会断线、需添加其他镜像)&repositories&
&repository&
&id&kafeitu&/id&
&url&http://maven.kafeitu.me/nexus/content/groups/public&/url&
&/repository&
&/repositories&
b. 添加依赖库,比如数据库驱动(这里不需要修改,使用默认h2数据库即可、且无需下载安装h2(已自带,否则反而要改版本号))&dependencies&
&dependency&
&groupId&com.h2database&/groupId&
&artifactId&h2&/artifactId&
&/dependency&
&/dependencies&
数据库连接修改:src/main/resources/db.properties(可选)给出一个改用Microsoft SQL Server的例子:db=mssql
jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=activiti
jdbc.username=sa
jdbc.password=
不过相应的,pom.xml中的数据库驱动依赖库就也需要添改:&dependencies&
&dependency&
&groupId&com.microsoft.sqlserver&/groupId&
&artifactId&sqljdbc4&/artifactId&
&/dependency&
&/dependencies&
工作流引擎配置修改:src/main/webapp/WEB-INF/activiti-standalone-context.xml&bean id="demoDataGenerator" class="org.activiti.explorer.demo.DemoDataGenerator" init-method="init"&
&property name="createDemoUsersAndGroups" value="true" /&
&property name="createDemoProcessDefinitions" value="true" /&
&property name="createDemoModels" value="true" /&
&bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"&
&property name="databaseSchemaUpdate" value="true" /&
Activiti工作流引擎配置、目前(5.16.3)采用Spring框架方式加载,以实现不同扩展的灵活配置。上手阶段所需做的修改,主要就是如上属性(分别用于自动生成Demo数据,以及比对引擎与数据库之间的版本、自动新建/升级数据库),更多可参考。
Maven项目刷新:Project右键菜单 & Maven & Update Project...,对于Maven项目来说,单单F5在文件系统层面刷新同步是不够的。
Maven项目编译:
命令行方式:较为简便,在你设置了PATH(包含%MAVEN_HOME%\bin)之后,便可在命令行窗口中、进入到Maven项目的根目录(pom.xml所在地)、然后执行Maven的系列命令了,如:
mvn compile
m2eclipse插件方式:更为简便,不过建议先搭建起调试环境(不同于.Net中attach到进程的方式,见后),然后直接在运行/调试前自动编译即可。
导入已有项目:,有了导入官方范例的基础,导入其他例子就很简单。
完整步骤(推荐用Maven方式):
基于Maven的Tomcat Web项目的断点调试也会有一番周折解决方法:
找到好文档,比如:,这篇是可行的。网上其他还有很多走弯路的方法。
定制补充REST API接口打通生命周天(周期)
经历过之前的准备,便可以导入这1.5个人月调研开发的成果项目了,上图,
图5:测试入口界面(Web客户端)
如果说activiti-explorer和kft-activiti-demo都是界面友好、前端与后台并重的话,这次项目则纯粹集中在后台(封装Activiti的引擎功能),因为前端界面(包括表单编辑器、邮件末班编辑器)将由.Net页面(一个企业内部门户网站)完成,衔接关系可参见图2(生命周期)。
项目的完成可划分为6个步骤:
Step1. 在官方范例activiti-explorer中嵌入activiti-rest前文推荐了导入官方范例项目activiti-explorer作为入门(+),在此第一步,我们就是在其基础上、加上对REST API的支持,也就是嵌入另一个官方范例activiti-rest。对于缺少J2EE/Spring项目经验的人可能会稍有障碍,其实两个官方范例项目合并的主要破解点如下:
web.xml 中的Listener配置:src\main\webapp\WEB-INF\web.xmlactiviti-webapp-explorer2(activiti-explorer的项目名)中的Listener配置,分别是Spring框架的ContextLoaderListener和RequestContextListener;而当你打开activiti-webapp-rest2(activiti-rest的项目名)则会发现,Listener只有org.mon.servlet.ActivitiServletContextListener,这是一个位于activiti-common-rest依赖包中的类、只用来启动和回收一个ProcessEngine类的实例。结论:我们无需合并该Listener,因为activiti-explorer已经采用Spring的Bean方式来加载ProcessEngine实例。
web.xml 中的Servlet配置:src\main\webapp\WEB-INF\web.xml官方范例(5.16.3为止)采用的是Restlet方式的REST实现,因此用到的servlet是org.restlet.ext.servlet.ServerServlet。我们将来扩展REST API将采用Spring MVC方式(后续),但对已有的REST API(5.16.3为止)、我们只能保留现有的Restlet方式入口,不过需注意,activiti-explorer范例与activiti-rest范例所用的org.restlet.application(Restlet方式下的入口类)并不相同,前者用的是一个只做了简单Router绑定的自定义类org.activiti.rest.explorer.application.ExplorerRestApplication、仅供modeler和diagram使用,后者(activiti-rest)用的则是包含较严格认证机制的org.activiti.rest.service.application.ActivitiRestServicesApplication,也因此如官方文档所述、标准REST API的调用都是的。结论:合并两个官方范例的org.restlet.application类,即使得activiti-explorer中的Restlet Application类、继承org.activiti.rest.service.application.ActivitiRestServicesApplication,覆盖其createInboundRoot()方法、补充入activiti-rest所需的RestServicesInit.attachResources(router);。
Step2. 再加入kft-activiti-demo的配置如从中文章可以看到,咖啡兔的范例,贡献了很多国内项目级别的成熟经验,比如:
中文化/国际化UTF-8
对官方标准REST API的调用、和不足之处的补充范例
Spring MVC方式的REST API扩展(尽管其结果也多以Spring MVC的ModelView方式返回、但入口与内部处理都足以借鉴)
这一步,我们所需做的就是把咖啡兔Demo中可借鉴的配置部分嵌入自己的项目中:
pom.xml最有价值的一段,就是借用咖啡兔的Maven私服(参见),否则在国内网络现状下甚至可能寸步难行。其次便是对于Spring框架、持续层的支持等等,值得注意的是,activiti-explorer作为activiti官方范例、是继承了其“上层”activiti-root的Maven配置的,而我们自己的项目、应该并不会希望建立这种继承,这种情况下,参照kft-activiti-demo的POM便是个safe的选择。
web.xml咖啡兔Demo同样使用Spring Bean方式加载,因此不需修改;同时因为咖啡兔Demo启用了Spring MVC架构、而这是我们将来扩展REST API时同样可以用的,因此需要搬运如下这一段:&servlet&
&servlet-name&springServlet&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&/WEB-INF/spring-mvc.xml&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&springServlet&/servlet-name&
&url-pattern&/&/url-pattern&
&/servlet-mapping&
其中spring-mvc.xml将负责具体的Spring MVC配置(后述)。
activiti-context.xmlSpring框架缺省调用的上下文配置文件是applicationContext.xml,咖啡兔Demo是直接把Activiti引擎所需要的配置写在其中的,activiti-explorer范例则是使用&import&把后台、前端的配置分在两个不同的文件中(activiti-standalone-context.xml和activiti-ui-context.xml)。作为我们自己的项目,只需合并在一个activiti-context.xml中即可。
spring-mvc.xml不长,直接留用,只需把&context:component-scan&中的base-package改成自己的项目包就可以;定制扩展的REST API将以一个个Spring MVC Controller的形式实现,这里的配置将实现对项目包下带有@Controller标签的类的自动扫描、实例化。
Step3. REST API学习RESTful服务的好处,如前所述、主要是能够使得业务系统所依赖的技术与工作流引擎所依赖的技术(Java)之间解耦。当Activiti引擎作为一个RESTful接口的Web服务运行时(输入输出可以都是JSON数据),浏览器、桌面、移动客户端、基于Java、.Net、Python都可与之交互。
URL风格仅以获取“流程设计模型一览”为例,这是一个标准REST API中就有的功能(),如果加上Spring Servlet的映射({servlet_mapping},在web.xml中已配置)等就形成完整的HTTP请求路径:GET http://{host:port}/{app_name}/{servlet_mapping}/repository/models
配置时则只需{servlet_mapping}之后的部分,例如GET repository/models
//表示获取“一览”
GET repository/models/{modelId}
//表示获取“某个个体”
POST repository/models
//表示“新建”一个个体
PUT repository/models/{modelId}
//表示“修改”某个个体
官方的Restlet方式REST实现官方的REST API实现(后台)就在activiti-rest范例中。URL模式与实现方法之间的映射,位于src\main\java\org\activiti\rest\service\application\RestServicesInit.java中:
router.attach("/repository/models", ModelCollectionResource.class);
router.attach("/repository/models/{modelId}", ModelResource.class);
进一步打开ModelCollectionResource类,可见Restlet方式的注释(Annotation)声明:
@Get("json")
public DataResponse getModels() {......}
public ModelResponse createModel(ModelRequest request) {......}
Restlet本身我们将不再沿用,但从映射所关联到的各个方法体中我们可以查找到各个功能的幕后实现。
Step4. REST API扩展对于标准REST API无法满足的需求,就需要自行扩展来实现了。扩展会涉及到将来Activiti引擎升级时的兼容问题,不过实际开发中发现、REST接口层的代码量相对来说是很薄的、即便其所用到的表层API发生了变化修改量也不会很大。
URL风格扩展API的{servlet-mapping}部分是与标准API有所区别的(比如一个是service另一个就是service-ext);其他URL风格方面则尽量与官方REST API保持一致。
Spring MVC方式REST实现在Spring MVC方式中,REST URL模式与实现方法之间的映射,直接位于各个实现方法所在的类中,包括位于类的声明、方法的声明之上的注释标签(@RequestMapping(...))。以“流程设计模型部署”为例,@Controller
@RequestMapping(value = "/service-ext/repository/models")
public class ModelController {
@RequestMapping(value = "deploy/{modelId}")
public String deploy(@PathVariable("modelId") String modelId,
@RequestParam(value="starterUser", required=false) String starterUserId,
@RequestParam(value="starterGroup", required=false) String starterGroupId,
RedirectAttributes redirectAttributes)
可以看到,deploy()方法所对应的URL模式是/service-ext/repository/models/deploy/{modelId},其中{modelId}部分将被直接解析成方法参数modelId,另外有两个方法参数starterUserId、starterUserGroup则对应的是URL中的QueryString部分(且是可选的),一个有效的HTTP请求可能是:GET http://localhost:8080/app/service-ext/repository/models/deploy/1111?starterUser=kermit
更完整的Spring MVC语法文档可参考,包括@ResponseBody的使用(方便的将对象返回值转成JSON等格式)、produces="application/json"、consumes="application/json"等等。
官方代码借鉴(略述)可根据与需求近似的REST API、找到与相关URL模式相映射的实现方法。activiti-engine核心包下的org.activiti.engine.impl.RepositoryServiceImpl等类是关键类,org.activiti.engine.mandExecutor则是引擎采用的“Command设计模式”的执行者,各种工作流操作都会被归结为相应的某种Command&Object&、在设置好特定的操作上下文CommandContext后、就由CommandExecutor负责执行。一般我们并不需要修改到Command设计模式的领域,而只需参考activiti-rest包中是如何调用其他包的代码就够。
Step5. 测试界面(客户端)如上,我们在后台每定制扩展一个REST API(e.g.“流程设计模型部署”),相应都需要在前端(Web)测试页面(如图5)中增加一组测试。注意:测试页面其实相当于是“业务系统”的角色,是可以与后台(工作流引擎)分隔为两个WebApp项目的。测试界面并未使用jquery-ui、blueprint等前端技术,只是简单的JSP(其实纯HTML/JS都完全可以,因为只需Ajax通信+JSON包装/解析)。给出一段调用“流程设计模型部署”API的HTML链接:
&a id="deploy_link"
href="${ctx}/service-ext/repository/models/deploy/&%=deploy_model_id%&?starterUser=&%=starter_user_id%&"&
流程设计模型部署
再给出一段部署后、已进入工作流运行时阶段(runtime)时、模拟用户提交某份表单完成某个用户任务的JS代码:
&script type="text/javascript"&
function onhandle(taskId){
var request = {
action: "complete",
assignee: "${userId}",
variables: [
{name: "complete_key_001", value: "complete_value_001"},
{name: "complete_key_002", value: "complete_value_002"},
{name: "complete_key_003", value: "complete_value_003"}
var request_json = JSON.stringify(request);
ajaxRequest("POST", "${ctx}/service-ext/runtime/tasks/complete/" + taskId, request_json, null);
function ajaxRequest(method, url, request, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
if(url.indexOf("/service/")&0){
//standard activiti REST api requires 1.Auth(base64) 2.POST 3.JSON header
xhr.setRequestHeader("Authorization", "Basic " + base64.encode("kermit"+":"+""));
if("POST" === method.toUpperCase() ){
xhr.setRequestHeader("Content-Type","application/json");
else if(url.indexOf("/service-ext/runtime/process-instances")&0)
xhr.setRequestHeader("Content-Type","application/json");
else if(url.indexOf("/service-ext/runtime/tasks")&0)
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = (callback!=null) ? callback : function() {
xhr.send(request);
Step6. 贯通生命周期根据你所服务的“业务系统”的不同,会对REST服务的接口提出不同的需求,甚至会影响到工作流生命周期的责任人划分:例如,流程设计模型究竟是能从官方Modeler直接兼容地保存到数据库、只需一个id即可部署,还是需要采用其他的Modeler编辑、然后以BAR/ZIP包方式直接部署、因此参数也就变成了文件流;或者说流程实例被启动后,某个用户名下的“我的(用户)任务”、究竟是点击后就“签收+办理”并弹出表单、还是分成两步进行。当我们逐一完成如图5的若干项 扩展或标准REST API调用,图2中展示的工作流生命周期也就能被打通了。工作流运行阶段、根据用户输入的不同、会进行不同的流转,可以通过官方范例中已有的流程状态跟踪器“Diagram Viewer”查看进度如下:
图6:运行时阶段的工作流状态查看
上图红线部分显示了,“填写申请”确认提交后经过了“直属上级审批”、但在“人事审批”环节被否决,又重新进入了“填写申请”环节。
本文记录了近2个月期间对开源工作流引擎Activiti做调研、贯通整个工作流生命周期(如图2)的过程,重点在于标识出同样没有相关基础的技术人员所可能碰到的陷阱、疑惑,希望能节省你的时间(少加几晚上班陪陪家人~);如有不正确/并非最优解的地方、也请有经验者指正。因为涉及雇主利益,除了知识点之外、完整源码就不能共享了。同时,因为业务系统中已包含自主开发的“表单编辑器”与“邮件模板编辑器”,这两部分内容(包括与引擎之间的具体衔接)不涵盖在本文范围之内。
举手一?,可添芳华
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
关注Java开发相关技术
· 6954人关注
举手一?,可添芳华
选择支付方式:

我要回帖

更多关于 activiti工作流demo 的文章

 

随机推荐