Activiti5需要jdk6以上的开发环境,Activiti6需要jdk7以上的开发环境,Activiti7支持云,Activiti Cloud是第一个云原生BPM框架,用于为云环境中的BPM实现提供可伸缩和透明的解决方案。
Activiti6支持与spring和springboot的集成,默认数据库是H2,可以支持mysql,oracle,db2,postgres,mssql等主流关系数据库,本文主要讲解基于springboot集成的activiti6的相关开发。
所需软件版本
springBoot 2.0.1.RELEASE
activiti 6.0.0,
activiti-modeler-5.22.0-sources.jar
activiti-webapp-explorer2
5.1 在POM文件中添加依赖
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
其他相关依赖见工程pom.xml
5.2 集成配置
activiti与springboot集成,相关配置可以通过yml文件或者配置类来实现,application.properties文件添加配置项。
spring.activiti.database-schema-update=true
databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:
l false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配时,将在启动时抛出异常。
l true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
l create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
l drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。
spring.activiti.history-level=full
对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:
l none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
l activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
l audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
l full:保存历史数据的*别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
其他相关配置
syncExecutorEnabled属性设置设置true后将代替那些老的Job executor
spring.activiti.async-executor-enabled=false
spring.activiti.job-executor-activate=false
asyncExecutorActivate是指示activiti在流程引擎启动就激活AsyncExecutor,异步
spring.activiti.async-executor-activate=
校验流程文件,默认校验resources下的processes文件夹里的流程文件
spring.activiti.check-process-definitions=
使用自定义mybatis-mapper
spring.activiti.custom-mybatis-mappers=
spring.activiti.custom-mybatis-xmlmappers=
数据源指定
spring.activiti.database-schema=
建表规则
flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。
true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。
create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。
drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
spring.activiti.database-schema-update=false
检测历史表是否存在
spring.activiti.db-history-used=false
检测身份信息表是否存在
spring.activiti.db-identity-used=false
流程部署名称
spring.activiti.deployment-name=
spring jpa使用
spring.activiti.jpa-enabled=false
邮件发送服务配置
spring.activiti.mail-server-default-from=
spring.activiti.mail-server-host=
spring.activiti.mail-server-password=
spring.activiti.mail-server-port=
spring.activiti.mail-server-use-ssl=
spring.activiti.mail-server-use-tls=
spring.activiti.mail-server-user-name=
自定义流程文件位置
spring.activiti.process-definition-location-prefix=
spring.activiti.process-definition-location-suffixes=
activiti rest 配置
spring.activiti.rest-api-enabled=false
spring.activiti.rest-api-mapping=
spring.activiti.rest-api-servlet-name=
5.3在线设计器拷贝项目资源
activiti6可以通过相关插件离线配置流程,也可以通过在线编辑配置流程。离线配置SpringBoot集成activiti默认会从classpath下的processes目录下读取流程定义文件,所以需要在src/main/resources目录下添加processes目录,并在目录中创建流程文件。
在线配置流程,通过如下方法:
解压activiti-webapp-explorer2,把webapp下面的diagram-viewer、editor-app、modeler.html复制到springboot项目下的static下,这是activiti的在线设计器,modeler.html就是设计的主界面,复制resources下stencilset.json到自己的resources下。
解压activiti-5.23.0的包,将libs下的activiti-modeler-5.23.0-sources.jar解压出来,把org\activiti\rest\editor路径下的main、model文件夹复制到springboot项目的源码路径下,里面有三个类,主要用于读取stencilset.json。
5.4修改拷贝过来的资源文件
修改如下3个controller,加上@RequestMapping("/service")
StencilsetRestResource.java
ModelEditorJsonRestResource.java
ModelSaveRestResource.java
修改editor-app下的app-cfg.js,把contextRoot后面改成 /service,和controller里面加的requestMapping要一致
5.5 用户信息及组整合
Activiti 中的用户与组用于界定任务的候选者与办理者。组可以理解为角色,属于某个组的用户,就可以作为某个任务的候选者或者办理者。我们还可以通过 Activiti 的 API 来创建、查询或删除某个用户或者某个组。Activiti 还提供了建立关系的 API 用于绑定用户与组之间的关系。如下图是用户与用户组相关的数据库表
在 Activiti 中,组的类型分为 assignment 和 security-role ,前者是普通角色,用于分配业务功能权限;后者是管理角色,用于管理组织结构与流程。用户与组之间的关系是多对多。一个用户可以归属于多个组;而一个组也可以包含多个用户。
需要说明的是,Activiti 用户和组也可以不整合,用业务系统中的用户角色数据库表。但是需要按照activiti接口规范提供用户角色相关的接口。如下图,对用户节点选择代理时,需要选择用户或者候选用户组(角色)。
如角色接口Get请求
http://localhost/sys/role/page?token=null&page=1&limit=20
用户接口get请求
http://localhost/sys/user/page?token=null&page=1&limit=20
5.6 配置模型
如下图,流程图需要完整的开始、结束节点,除此之外,需要有用户节点,如果有互斥网关,需要指定分支流转条件,中间节点需要有输入,输出,且输入输出箭头需要指定具体的节点,不能出现箭头指向为空。如果有子流程,子流程中也需要有完整的开始,结束节点。
配置代理人,用户和组可以指定具体人,动态配置可以用${xxx}来表示。如${auditUserId},用户提交时,就需要传递auditUserId参数变量。
5.7 多实例模型配置说明
多实例可以配置在各种类型的任务节点、子流程、回调活动节点上。下图红色方框是涉及多实例需要配置的字段:
A.多实例包含的默认变量
多实例包含的默认变量,可以通过execution.getVariable(x)方法获取:
nrOfInstances:创建的实例总数;
nrOfActiveInstances:当前活动的实例数,针对顺序类型的多实例,该变量值等于1;
nrOfCompletedInstances:已执行实例数;
loopCounter:表示多实例流程循环的下标。
基于如上变量,可以设置多实例任务的流转条件。如需要2/3通过,就可以设置流转条件为${nrOfCompletedInstances/nrOfInstances==2/3}。如下图:
B.多实例类型
顺序(sequential ):按顺序出实例,当前活动实例数(nrOfActiveInstances)一直是1
并行(parallel):多个实例会同时并行发放给处理人。
C.基数(多实例)
定义多实例生成的实例数。当结合采集方式生成多实例时,该基数只能小于或等于采集集合的size,否则执行过程中将发生系统错误 NoSuchElementException;当基数小于采集集合的size时,则按照集合中元素的顺序生成等于基数指定数量的实例。如果不配合使用采集方式,也可以直接指定基数,则系统会同时生成指定数量的相同实例。
D.采集(多实例)/集合(多实例)
用于指定一个List,自动生成等于List size数量的实例。可以将该List设置为处理人员列表,然后设置元素变量名,并将分配—固定值—处理人/代理人设置为元素变量名,则最后会为每一个集合中的人员生成一个已指派实例。
E.元素变量(多实例)
表示多实例采集中元素对应的变量,该变量保存着集合中元素的最新值,可以使用表达式获取。
F.完成条件(多实例)
是一个表达式,如果返回值为true则该多实例自动结束。例如 ${nrOfCompletedInstances/nrOfInstances >= 0.6 } 只要所有流程实例完成了60%即该多实例任务结束。
G.分配/代理
在使用多实例的情况下,当将分配—固定值—处理人/代理人/候选人设置为多实例元素变量名时,则生成的实例会对应自动指派给列表中配置的处理人。
5.8 配置并行多实例用户任务模型举例
在很多情况下,我们需要多用户共同执行余下流程,比如开会流程:领导发起开会,选择开会人员(多个),每个开会人员接收到通知后需要签到(一名用户签到不会影响到另一位用户的签到),签到完成后则流程结束。此时,就需要用到多实例(多任务)。
A.创建模型
B.领导发起开会
由于具体是哪个领导发起开会有不确定性(只要是领导都可以发起),所以需要设置代理人属性:Assignee: ${leader} 。
为了方便后面的【开发人员签到】流程,我们还需要在【领导发起开会】流程处设置一个流程执行监听器(此操作不是必须,此处只是为了解释动态多实例),在Activiti中,配置监听器需要在模型和JAVA中都进行相应配置:在JAVA中我们想要创建监听器只需要创建一个类,并实现系统监听器类 ExecutionListener 即可,代码如下:
接下来就是模型中的配置,由于我们想在领导指派了开会人员后进行监听,所以需要如下设置
其中 Event 代表事件触发类型,作用如其名Class 代表监听器全路径,此处为 com.kenary.activiti.listener.MyExecutionListener,则是之前创建的 MyExecutionListener。监听器配置完成后领导发起开会流程就配置完成。
C.开会人员签到
相对于领导发起开会流程,开发人员签到流程则需要配置更多内容。
其中,集合(Collection)设置的是存储开会人员集合的变量名,注意:此处不需要${},并且 变量的值必须是 Collection的子类,即List、Set等。
多实例类型设置的是并行、串行等方式。并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响。串行代表工作或任务由一个人完成后,再由另一个人去处理,直至全部完成,每个任务依赖于前一个任务完成。
元素变量(Element variable) 设置的是集合(Collection)每遍历一次设置的变量值的变量名,即迭代集合时存储集合里面单个元素的变量名,集合遍历时会根据内容创建任务。
代理设置的是处理该任务的用户,由于集合每遍历一次就创建了一个任务,所以这里和领导发起开会流程无太大差异,指定代理人即可,不过代理人员需要使用元素变量(Element variable)(Item 迭代的值)。
流程配置后,需要保存。