- 第一章 认识Activiti
- Activiti七大Service接口
- Activiti与jBPM5比较
- 注意
- 第2章 Acitiviti与BPMN 20规范
- 启动事件与结束事件
- 空启动事件
- 定时启动事件
- 异常启动事件
- 消息启动事件
- 空结束事件
- 异常结束事件
- 终止结束事件
- 取消结束事件
- 顺序流
- 任务
- 用户任务
- 脚本任务
- Java Service 任务
- 业务规则任务
- 邮件任务
- Camel任务
- 手动任务
- 接收任务
- Shell 任务
- 多实例
- 网关
- 排他网关 Exclusive Gateway
- 并行网关
- 包容网关
- 事件网关
- 子流程与调用活动
- 子流程
- 调用活动
- 边界与中间事件
- 边界事件
- 启动事件与结束事件
- 监听器
- 执行监听器
- 任务监听器
- 用户与组及部署管理
- 用户与组
- 用户
- 组
- 用户任务中的用户与组
- 候选组
- 用户与组
第一章 认识Activiti
Activiti七大Service接口
Service接口 | 作用 |
---|---|
RepositoryService | 流程仓库Service,用于管理流程仓库,例如,部署,删除,读取流程资源 |
IdentifyService | 身份Service,可以管理和查询用户,组之间的关系 |
RuntimeService | 运行时Service,可以处理所有正在运行状态的流程实例,任务等 |
TaskService | 任务Service,用于管理,查询任务,例如,签收,办理,指派等 |
FormService | 表单Service,用于读取和流程,任务相关的表单数据 |
HistoryService | 历史Service,可以查询所有历史数据,例如,流程实例,任务,活动,变量,附件等 |
ManagementService | 引擎管理Service,和具体业务无关,主要是可以查询引擎配置,数据库,作业等 |
Activiti与jBPM5比较
技术组成 | Activiti | jBPN |
---|---|---|
ORM框架 | MyBatis3 | Hibernate3 |
持久化标准 | 无 | EJB JPA规范 |
事务管理 | MyBatis自带/Spring继承事务 | Bitronix,基于JTA事务管理 |
数据库连接方式 | JDBC/DataSource | JDBC/DataSource |
Spring支持 | 原生支持Spring,在流程中可以使用Spring代理的Bean作为表达式的一部分,并且支持JPA及事务管理 | 默认没有提供对Spring的支持 |
支持的数据库 | Oracle,SQL Server,MySQL,H2,内存数据库等 | Oracle,SQL Server,MySQL,内存数据库等 |
设计模式 | 命令模式,观察者模式等 | |
内部服务通信 | Service间通过API调用 | 基于Apache Mina异步通信 |
集成接口 | SOAP,Mule,RESTful | 消息通信 |
技术组成 | Activiti | jBPM |
支持的流程格式 | BPMN2,xPDL,jPDL等(由PVM实现) | 目前仅支持BPMN2.xml |
引擎核心 | PVM(流程虚拟机) | Drools |
技术前身 | jBPM3,jBPM4 | Drools Flow |
团队成员 | 除了Alfresco公司的雇员之外还有Spring-Source,MuleSoft,Salves,Signavio,FuseSource,NextLevel等公司的员工加入 | 有一个专门的团队,此外还有一些个人参与者 |
附加工具 | 提供了基于Eclipse插件的流程设计器–Eclipse Degigner,提供基于REST风格的Activiti Explorer,可以用来管理仓库,用户,组,启动流程,任务办理等 | 同样提供Eclipse 插件和一个Web应用管理流程等 |
发布周期 | 固定每两个月发布一版,其中包括:引擎,Eclipse Designer,Activiti Explorer,REST应用 | jBPM的发布周期相对来说不太固定,发布内容包括引擎及基于Eclipse的设计器 |
注意
在Activiti 5.9以及之前的版本中,流程引擎在读取流程定义文件时必须以bpmn20.xml结尾。从Activiti 5.10 版本开始,Activiti已经支持直接部署以bpmn扩展名结尾的流程定义文件。
第2章 Acitiviti与BPMN 2.0规范
启动事件与结束事件
启动事件都是”捕获型”,等待第三方触发后才可以启动。结束事件总是抛出型的,也就是当流程执行到结束事件时会抛出一个执行结果。
空启动事件
- activiti:formKey 指定空启动事件关联的表单文件
- activiti:initiator 记录启动流程的人的ID
定时启动事件
- timeDate 一次性定时启动,具体到一个日期
- timeDuration 设置多长时间之后启动流程
- timeCycle 周期性启动任务,设定循环的时间间隔
异常启动事件
可以触发一个异常子流程,但是不能通过API(runtimeService.startProcessInstance()方法)方式启动,它总是在另外一个流程抛出异常结束事件的时候被触发
异常启动事件是捕获型,而异常结束事件是抛出型,和Java异常处理机制类似。异常结束事件对应throw,异常启动事件则是catch,并且执行catch后获取不同类型的异常。
消息启动事件
可以通过一个消息名称触发(可以通过Activiti提供的API触发消息启动事件),从而启动一个流程实例;还可以结合消息抛出事件一起使用。
空结束事件
抛出型,不处理抛出结果。一般用于正常结束流程。
异常结束事件
有抛出结果的。它定义了需要抛出的错误代码,如果找到了异常开始事件定义的异常代码,则会触发异常开始事件,否则按照空结束事件规则处理。
终止结束事件
结束事件中比较特别的类别,可以终止一个流程实例的执行。(例如在付费流程中因为某些原因导致流程不能继续运行,最终结果是取消本次付费,所以需要提前结束流程实例的执行)
取消结束事件
可以取消一个事务子流程的执行,同时也只能在子流程中使用。当子流程执行过程中出现异常需要取消时,可以设置一个取消结束事件,当输出流指向到取消事件时,流程将会中断执行。
顺序流
- 标准顺序流
- 条件顺序流
任务
- 用户任务
- 脚本任务
- WebService任务
- 业务规则任务
- 邮件任务
- Mule任务
- Camel任务
- 手动任务
- Java Service任务
- Shell 任务
用户任务
必须被人为触发(完成任务动作)
- humanPerformer 分配给一个人
- potentialOwner 分配给多个候选人
formalExpression里的候选人如果不指定user或是group,BPMN 2.0规范默认指定为group
属性名称 | 属性说明 |
---|---|
activiti:assignee | 用来指定用户任务的处理人,代替了humanPerformer的功能 |
activiti:cadidateUsers | 用来指定用户任务的候选人,多个用逗号,代替了potentialOwner的功能 |
activiti:cadidateGroups | 用来指定候选组,多个用逗号分开,代替了potentialOwner的功能 |
activiti:dueDate | 设置用户任务到期日,通常用变量代替而不是指定一个具体的日期,因为这样毫无意义 |
activiti:priority | 用户任务的优先级,取值区间[0, 100] |
脚本任务
运行引擎依赖的语言之外的脚本语言,例如Groovy,JavaScript,Juel。
Java Service 任务
不属于BPMN 2.0 规范,而是Activiti扩展的专门应用于Java语言的servickeTask。
属性名称 | 属性说明 |
---|---|
activiti:class | 实现了接口JavaDelegate或ActivitiBehavior的Java类 |
activiti:expression | 使用UEL定义需要执行的任务内容 |
activiti:delegateExpression | 功能和activiti:class类似,而且同样需要实现JavaDelegate或ActivityBehavior中的一个接口 |
acitivit:resultVariable | 仅适用于activiti:expression类型的Java Service |
业务规则任务
支持比较流行的JBoss规则引擎–Drools,只需把含有业务规则任务的流程文件和规则引擎文件.drl一同打包部署到系统中。
邮件任务
不属于BPMN 2.0 规范,而是和Java Service任务类似,由Activiti扩展而来专门用于处理邮件任务。在serviceTask的基础上由Activiti添加了扩展属性activiti:type=”mail”实现的。
Camel任务
不是BPMN 2.0 规范,是Activiti在serviceTask的基础上扩展的任务模型,是EIP(Enterprise Integration Patterns,企业集成模式)的实现,用来解决消息路由的框架。类似的产品有Mule, Spring Intergretion等
Mule任务和Camel任务一样,也不是BPMN 2.0 规范的一部分,Activiti针对Mule任务进行了整合,可以直接在流程中通过添加Task的方式调用Mule处理业务逻辑。
Activiti对Camel的扩展使用的是serviceTask,而对于Mule任务使用另外一种发送任务–sendTask
手动任务
比较特殊,不做任何事情,仅用来定义BPM不能完成的任务,需要人工参与建模,流程引擎无需关心如何处理它,因为根本不需要处理,所以Activiti把手动任务当做一个空任务来处理,当到达此任务时由因引擎自动完成并转向到下一个任务
接收任务
在任务创建之后开始等待消息的到来,直到被触发才会完成任务。Activiti实际上把接收任务当作一个Java类型的接收任务,仅能通过RuntimeService接口的signal()方法发送信号(signal)触发接收任务。
Shell 任务
允许在流程运行过程中执行本地操作系统中的脚本,命令。是Activiti基于serviceTask扩展的一种任务。
多实例
多实例允许业务流程中某一个任务甚至子流程可以重复执行多次,在实际应用中一个申请由多人审批是多实例的典型应用场景。多个实例可以选择顺序执行,还可以选择并行执行多实例任务或子流程。
多实例支持如下类型:
- 用户任务
- 脚本任务
- Java Service 任务
- Web Service任务
- 业务规则任务
- 邮件任务
- 手动任务
- 接收任务
- 子流程(嵌入式)
- 子流程(调用活动)
多实例的常用属性变量(通过execution.getVariable()获取)
- nrOfInstances 实例的总数
- nrOfActiveInstances 当前活动的(未完成的)实例数量,对于按照顺序执行的多实例,该值总是1
- nrOfCompletedInstances 已经完成的实例数量
- loopCounter 多实例运行过程中,for-each循环中当前的索引值
决定启动多少个流程实例可以从两个角度设置:固定数量,任务参与人列表
网关
- 排它网关
- 并行网关
- 包容网关
- 事件网关
排他网关 (Exclusive Gateway)
用来对流程中的决定进行建模。流程执行到该网关时,按照输出流的顺序逐个计算,当条件计算结果为true时,继续执行当前网关的输出流。排他网关需要和条件顺序流配合使用,一个排他网关可以连接多个条件顺序流,每个顺序流设置一个条件在运行时由引擎计算并根据计算是否为true决定执行与否。当所有的条件都不满足时,排他网关会默认执行exclusiveGateway的default属性指定的条件顺序流(此时已经忽略了默认流的条件)。
值得注意的是,在排他网关中,如果多个线路的计算结果都为true,那么只会执行第一个值为true的网关,忽略其它表达式的值为true的网关。如果多个网关计算结果都没有为true的值,则引擎会抛出异常。
并行网关
并行网关用来对并发的任务进行流程建模,它能把单条线路任务拆分(fork)成多个路径并行执行或将多条线路合并(join)。并行网关的功能取决于输入,输出顺序流
- 拆分 并行执行所有的输出顺序流,并且为每一条顺序流创建一个并行执行路线
- 合并 所有从并行网关拆分并执行完成的线路在此等候,直到所有的线路都执行完成才会继续向下执行
并行网关不会计算线路上设置的条件,如果设置了,则会被直接忽略
并行网关还允许在线路上嵌套并行网关,也就是在fork拆分的线路上再添加n个fork线路,只要保证最后有一个join点合并拆分的线路即可。
如果一个并行网关有多个输入,输出流,那么它同时具备fork和join的功能,对于这样的网关,首先会合并被拆分的并行网关线路,然后再拆分合并网关之后的线路。
包容网关
包容网关融合了排他网关和并行网关的特性,排他网关允许在每条线路上设置条件,并行网关可以同时执行多条线路,包容网关既可以同时执行多条线路,又允许在网关上设置条件。
和并行网关一样,包容网关的功能也取决于输入,输出顺序流
- 拆分 计算每条线路上的表达式,当表达式计算结果为true时,创建一个并行线路并继续执行
- 合并 所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完才继续向下执行。
事件网关
事件网关是专门为中间捕获事件设置的,它允许设置多个输出流指向多个不同的中间捕获事件(最少两个)。在流程执行到事件网关后,流程处于等待状态,因为中间捕获事件需要依赖中间抛出事件触发才能更改等待状态为活动状态,当然,定时器捕获事件除外(它由时间驱动)
关于事件网关,需要注意几点
- 事件网关的输出流数量必须大于2个
- 事件网关的输出流类型只能是中间捕获事件,Activiti不支持接受任务后面的事件网关
- 中间捕获事件的输出流只能有一个
子流程与调用活动
调用活动的特点与子流程类似,但是子流程嵌入在主流程中,要保持通用需要把付款流程作为活动由主流程调用,如此调用活动既包含了子流程的特性,又保持通用。
子流程
对于子流程,BPMN 2.0 对其做了一些限制
+ 只能且仅能包含一个空启动事件
+ 至今要有一个结束事件(每个流程都要”有始有终”)
+ 在子流程中顺序流不能直接设置输出流到子流程之外的活动上,如果需要的,可以通过边界事件代替
子流程需要把一系列模型包含在一个实线矩形中,子流程不能直接越界指定输出流,也就是说子流程中的输出流只能指向在实线边框内的活动,如果因为异常需要终止子流程的执行可以通过后面介绍的边界事件处理。
调用活动
调用活动解决的问题是流程的通用性。和子流程的作用一致,但是表现方式不同,使用一个调用活动取代嵌入子流程方式的活动即可。
边界与中间事件
除了启动和结束事件之外,中间事件提供的特殊功能可以用来处理流程执行过程中抛出,捕获的事件,具体包括边界事件,中间捕获事件,中间抛出事件。
边界事件
边界事件是绑定在活动上的捕获型事件,会一直监听所有处于运行中活动的某种事件的触发,在捕获到事件之后中断活动,然后从边界事件类型的输出流继续执行。
值的注意的是一旦触发边界事件,当前的活动就会被中断,然后按照边界事件之后的输出流执行
- 定时器边界事件
- 异常边界事件
- 信号边界事件
- 补偿边界事件
监听器
在Activiti中开发人员可以通过配置监听器的方式监听各种动作,例如流程启动,结束,任务创建,任务完成,甚至是经过某个顺序流时。
监听器分为两类:执行监听器和任务监听器
执行监听器
执行监听器运行在执行流程过程中执行Java代码(实现了监听器接口)或表达式
执行监听器可以捕获的事件如下:
- 流程实例启动,结束
- 输出流捕获
- 活动启动,结束
- 路由开始,结束
- 中间事件开始,结束
- 触发开始事件,触发结束事件
执行监听器使用Activiti的扩展元素定义,通过event属性指定监听事件的类型(分为三类:start,take,end),并且可以选择监听器执行类型
监听器执行类型 | 属性说明 |
---|---|
class | 需要实现接口org.activiti.engine.delegate.ExecutionListener |
expression | 定义一个表达式,类似EL的语法 |
delegateExpression | class属性必须显示指定一个class的全路径,如me.kafeitu.ExecutionListenerXxx。在有些情况下需要根据因为业务的不同动态指定一个接口实现,delegateExpression允许指定一个实现了监听接口的(参考class属性的限制)类的name,具体的类可以在引擎配置中配置或由Spring打理。 |
3种监听器执行类型只能使用其中一种
class类型
<activiti:executionListener event="start" class="me.kafeitu.listener.ExecutionListenerForStart"/>
expression类型
<activiti:executionListener expression="${pojo.method(execution.eventName)}" event="end"/>
这里的pojo是一个Bean的名称(可以用Spring代理),还可以在expression中通过计算一个表达式配置监听器的名称
delegateExpression类型
<activiti:executionListener event="start" delegateExpression="${executionListenerBean}"/>
其中${executionListenerBean}为一个Bean对象的名称
任务监听器
相对于执行监听器的使用范围来说,任务监听器的使用范围要小很多,因为它只能应用于用户任务,用来监听3种事件。
- create:在任务被创建且所有的任务属性设置完成之后才触发
- assignment:在任务被分配给某个办理人之后触发。
- complete:在配置了监听器的上一个任务完成时触发,也就是在运行时任务数据被删除之前(Activiti的数据分为运行时和历史两种类别,当运行时数据处理完成将会被清理)触发
有一点需要注意:assignment事件总是在create事件触发之前被触发,因为任务的办理人是一个属性,而create事件需要逐一处理任务的办理人,候选人,候选组属性。
任务监听器的3种监听器执行类型
监听器执行类型 | 属性说明及示例 |
---|---|
class | 需要实现接口org.activiti.engine.delegate.TaskListener |
expression | 定义一个表达式,类似EL语法 |
delegateExpression | class属性必须显示指定一个class的全路径,在有些情况下需要根据业务的不同动态指定一个接口实现,delegateExpression允许指定一个实现了监听接口类的name,具体的类可以在引擎中配置或由Spring代理 |
用户与组及部署管理
用户与组
用户
在Activiti中,用户和组主要是应用于用户任务(userTask)
组
组是控制权限的一种方式,属于某个组的用户就拥有操作某些功能的权限。在Activiti中,组的类型分为两种,即assignment和security-role,前者为一种普通的岗位角色,是用户分配业务中的功能权限,后者是安全角色,可以从全局管理用户组织及整个流程的状态。
用户任务中的用户与组
候选组
当不确定要将一个任务分配给哪个人办理时,就需要把任务指定给多个候选人或候选组。意思就是属于这个组的用户都可以是潜在的办理人,但是大家都遵守一个规则:谁签收了这个任务,谁就可以办理任务。
未晚待续。。本笔记均从咖啡兔的《Activiti实战》整理出来。