activiti工作流教程引擎是多租户还是单租户??

多租户概念以及FreeLink多租户设计思想 - CSDN博客
一、多租户概念
1.什么是多租户
  多租户技术(英语:multi-tenancy technology)或称多重租赁技术,是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。 
  呼叫中心为了开展呼叫中心座席租赁业务,希望在自己建立的一套呼叫中心系统平台上就能够实现多个租户的外包业 务。呼叫中心要求在一套呼叫中心系统上可以满足多个租户共用或租户独享物理的硬件资源,而在逻辑上每个租户像是拥有自己独立的虚拟呼叫中心,可以使 用呼叫中心的全部功能和个性化呼叫流程。每个租户逻辑上是独立的,租户之间互不干扰,数据隔离。
2.多租户管理至关重要
  为了不同租户的呼叫中心或商业企业在一个共享的外包呼叫中心系统平台中独立安全的运营,呼叫中心的多租户管理是关键。租户的自我管理使得单独的租户 独立的管理他们自己的呼叫中心而不需等待外包呼叫中心的技术专家服务。呼叫中心的基本技术设计理念是一个真正的多租户平台,具备先进的租户自我管理 特色。这样完美的平台适合于想要节省开支的BPO(业务过程外包)企业,或者想在同一个呼叫中心平台上增强管控的公司,也可以给想要提升效率和盈利的专业提供外包服务的呼 叫中心。
3.租户的自我管理
  租户自我管理本着双赢的目标,为BPO服务商和租户提供更易使用及更高效的呼叫中心。BPO 服务商从租户的自我管理中获益,无需亲自来操心租户的日常管理工作,减少了单独为租户配备专业技术服务人员的运营管理成本和麻烦。租户也从可以自己灵活调 整坐席路由及流程中获益,无需等待外包呼叫中心的技术专家来服务。不论业务结构有多复杂,组织结构有多少层,呼叫中心的安全调整机制都能让呼叫中心 的经理们去满足客户需求。这使得呼叫中心的任何人都能在任何时间,任何地点做出准确的调整,不会多,也不会少。
4.真正的多租户
  为了保证BPO呼叫中心的完整利益,一个真正的多租户呼叫中心平台尤其重要。有些呼叫中心厂商虽然宣称是多租户,但是实际上他们的做法是为每一租户提供 一套专有平台。对于租户来说,似乎差异很小。但是在后期运营的时候,实时的调整呼叫中心的配置及流程都要花费高额的代价。  
5.对BPO企业的好处
  系统维护人员仅需通过一个易用的B/S界面管理全部租户;先进的安全模型及系统模块特征确保租户使用安全并且和其他租户彻底隔离;租户可以将坐席资源及 服务器资源动态优化至合理的水平;统计系统能够准确记录系统的数据,并能为其他的计费系统提供详实准确的数据;一个单独的系统可以支持1000个租户,确 保BPO企业能维护足够多的租户。
6.对租户的好处
  租户无需额外的服务就能管理自己的呼叫中心系统,即使每天去调整坐席 队列,技能组,更改坐席技能,更换路由策略和报表都可以得心应手;管理人员可以通过一个既易用又安全的B/S界面来调整队列和路由参数,以适应大量的企业 需求;租户可以随意调整IVR和ACD。这样的工作仅需使用拖、拉、拽的的形式即可完成调整;租户可以通过B/S的实时监控系统和事后统计报表来观察企业 用户的行为,也可以为企业提供单独的定制报表。而不像其他厂商仅能提供统一的报表;租户可以通过B/S的录音管理界面来查询、调听和下载本企业客户的电话 录音,各租户之间客户录音相互隔离。租户自己也可以为企业内部用户管理访问录音的权限。
7.将多租户模型平台化
  大家都知道寻找和积累客户不容易,这些信任我们并正在使用我们系统的客户的价值当然不容忽视。既然有这么多客户了,何不就针对他们的行业需要来引入一些行业软件供他们使用,而不仅仅是呼叫中心呢?
  将平台开放出来,由我们或第三方来开发一些有针对性的功能,以插件的形式供现有的客户使用,客户需要哪些功能,就租用哪些功能,不仅降低方便了客户,省去了我们寻找和开发客户的步骤,而且能进一步扩大平台的客户量,形成一个良性循环。
8.呼叫中心多租户架构图
二、多租户实现思想
  多租户技术的实现重点,在于不同租户间应用程序环境的隔离(application context isolation)以及数据的隔离(data isolation),以维持不同租户间应用程序不会相互干扰,同时数据的保密性也够强。
  1.应用程序部分:通过进程或是支持多应用程序同时运行的装载环境(例如Web Server,像是Apache或IIS等)来做进程间的隔离,或是在同一个伺服程序(server)进程内以运行绪的方式隔离。
  2.数据部份:通过不同的机制将不同租户的数据隔离,Force是采用中介数据(metadata)的技术来切割,微软 MSDN 的技术文件则是展示了使用结构描述的方式隔离。
  多租户就是说多个租户共用一个实例,租户的数据既有隔离又有共享,从而解决数据存储的问题。从架构层面来分析,SaaS区别于传统技术的重要差别就是Multi-Tenant模式。
  SaaS多租户在数据存储上存在三种主要的方案,分别是
1.独立数据库
  这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本也高。
  优点:
  为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。
  缺点:
  增大了数据库的安装数量,随之带来维护成本和购置成本的增加。这种方案与传统的一个客户、一套数据、一套部署类似,差别只在于软件统一部署在运营商那里。如果面对的是银行、医院等需要非常高数据隔离级别的租户,可以选择这种模式,提高租用的定价。如果定价较低,产品走低价路线,这种方案一般对运营商来说是无法承受的。
2.共享数据库,隔离数据架构
  这是第二种方案,即多个或所有租户共享Database,但一个Tenant一个Schema。
  优点:
  为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可以支持更多的租户数量。
  缺点:
  如果出现故障,数据恢复比较困难,因为恢复数据库将牵扯到其他租户的数据;如果需要跨租户统计数据,存在一定困难。
3.共享数据库,共享数据架构
  这是第三种方案,即租户共享同一个Database、同一个Schema,但在表中通过TenantID区分租户的数据。这是共享程度最高、隔离级别最低的模式。
  优点:
  三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。
  缺点:
  隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量; 数据备份和恢复最困难,需要逐表逐条备份和还原。如果希望以最少的服务器为最多的租户提供服务,并且租户接受以牺牲隔离级别换取降低成本,这种方案最适合。
  CRM系统未来将以中低端市场为主,所以采用第三种方案,只要做好数据隔离比较好了。千万不可掉以轻心,SaaS下的安全性设计很重要。一般常见的安全性设计分为两类:系统级和程序级。
  系统级:
  使用HTTPS协议以SSL(Security Socket Layer)交换数据,增强通信安全;通过数字签名防止传输过程篡改;对用户身份识别的UserToken使用DES算法数据加密;业务数据定时自动备份。
  程序级:
  完整的权限配置,包括功能权限和数据权限;客户端输入校验,防止JS攻击、XSS攻击、SQL注入等;辅助安全设计,比如密码控件、图片验证码、手机确认码等。
三、多租户特点
  1.由于多租户技术可以让多个租户共用一个应用程序或运算环境,且租户大多不会使用太多运算资源的情况下,对供应商来说多租户技术可以有效的降低环境建置的成本。包含硬件本身的成本,操作系统与相关软件的授权成本都可以因为多租户技术,而由多个租户一起分担。
  2.通过不同的数据管理手段,多租户技术的数据可以用不同的方式进行数据隔离,在供应商的架构设计下,数据的隔离方式也会不同,而良好的数据隔离法可以降低供应商的维护成本(包含设备与人力),而供应商可以在合理的授权范围内取用这些数据分析,以作为改善服务的依据。
  3.多租户架构下所有用户都共用相同的软件环境,因此在软件改版时可以只发布一次,就能在所有租户的环境上生效。
  4.具多租户架构的应用软件虽可客制,但客制难度较高,通常需要平台层的支持与工具的支持,才可降低客制化的复杂度。
四、Genesys多租户技术
五、多租户应用实例
  多租户技术在实务上运用的成功且广为人知的案例之一,是由Salesforce所建置的CRM应用系统,该公司除了Salesforce的CRM软件以外,它还建置了Force平台即服务(PaaS)架构,以支持开发人员发展基于Force平台上的应用程序。在云计算的加持之下,多租户技术被广为运用于开发云各式服务,不论是IaaS,PaaS还是SaaS,都可以看到多租户技术的影子。
  华为呼叫中心多租户实例:
  针对部分企业对数据和应用绝对安全的要求,可以在外包租户侧部署WEB service的企业应用代理,为企业业务预留访问接口。企业数据无需上传,涉及企业内部业务访问由应用触发调用企业应用代理服务,数据应用和修改全部在企业侧完成。所有传输基于高可靠性加密协议进行。
六、FreeLink多租户设计
2.主要功能
2.1 话务功能  
  分租户IVR语音导航
   o每个租户灵活定制独立的IVR语音导航菜单
  分租户资源控制
   o对每个租户进行资源限额,包括出入中继、会议资源、TTS资源、ACD资源、硬盘空间等
  分租户实时话单
   o对每个租户提供独立的话单脱机文件
   o对每个租户提供实时话单实时通信接口
  系统运行监控
   o图形化方式实时监控资源、话务、中继利用情况,在线调整运行参数
2.2 管理功能
  分租户管理
   o分租户管理
   o增加、删除、修改企业账户。
  分租户限呼配置
   o按照企业要求,对企业进行呼叫限制。
  分租户中继组配置
   o根据企业分配的容量,配置企业中继组,保证高并发情况下通信线路的可用。 
  分租户数据备份和恢复
   o对企业数据进行备份和恢复,保证应用安全。 
  分租户计费与话单
   o企业计费查询:企业可通过平台查询本企业的计费详单
   o企业详单管理:企业可通过平台查询本企业的通话详单 
  分租户录音管理
   o可选择性对通话进行录音,对录音进行完善的概率,提供专用录音查询方式和电话提取录音方式。 
  分租户语音信箱
   o每个租户下的用户可设定独立的语音信箱,当来话遇忙或无人应答时,在系统的提示下主叫用户可以选择转至语音信箱进行留言。 
  分租户传真管理
   o可通过IVR导航直接收取传真,或呼入到内线用户分机后转传真。
2.3 管理平台
  呼叫中心为企业业务管理人员、系统管理人员等提供多级、多层次的管理门户。提供平台管理、资源管理、应用管理、认证管理、权限管理等。
  统一门户采用Web架构,门户的用户远程登录后,根据其角色和权限提供相应的操作界面。具体功能包括:
  (1)平台管理 完成呼叫中心多服务域的管理,对多服务域、服务节点、服务单元进行监控,实时监测服务运行状态。
  (2)资源管理 支持企业查询、配置各种资源包括不限于座席数,IVR数,以及服务器(座席服务器、IVR服务器、SIP服务器、文件服务器)资源,服务号码,SIP号码,话务员号码等等。
  (3)应用管理 支持各种商业模式下的应用管理,完成应用查询、应用申请、应用终止操作。   
应用查询 提供界面供企业查询系统提供的应用和合作伙伴提供的应用综合列表。
应用申请 提供操作界面供企业管理员完成应用受理、应用审核。
应用终止 提供操作界面供企业管理员完成应用终止,客户提出应用终止申请后,管理员审核终止工单,完成应用终止。
& & & &(4)认证管理 当平台加载服务时,服务需通过认证及授权后,方可以使用平台的网络及计算资源。当一个服务请求平台加载,业务运行环境首先审核该服务片段所包括证书的合法性,如果证书合法,审核服务内容的一致性,如一致性审核通过,审核服务对归属地及媒体网络的使用权限。 服务认证系统应提供详细的服务使用记录,作为服务统计及计费的原始记录。
  (5)权限管理 实现权限管理和用户鉴权,提供灵活强大的用户鉴权机制,使不同地点、不同部门、不同权限的用户拥有各自的菜单界面,并查询和管理各自的业务信息。Activiti进行时——企业工作流生命周期贯通 - 简书
下载简书移动应用
写了17651字,被2人关注,获得了6个喜欢
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开发相关技术
· 1705人关注
让有价值思想的传播者、也能借新平台有属于他们的一份收获;即使不打赏,有效交流,也是对整个集体的...
选择支付方式:

我要回帖

更多关于 activiti工作流视频 的文章

 

随机推荐