Activiti,2010年基于jBPM诞生
Flowable,2016年预计Activiti诞生
Comframe,asiainfo的工作流框架,从时间上推测,用的可能是jBPM2.0或3.0
原Activiti的Tijs Rademakers团队去开发Flowable框架。
现Activiti7是 Salaboy团队开发的,内核使用的还是Activiti6,扩展了云化。Activiti5、Activiti6代码目前由 Salaboy团队代为维护,目前官宣已经暂停维护。
对比项\引擎 | Activiti-7.x | Flowable-6.x | Camunda- |
---|---|---|---|
商业化 | √ | √ | √ |
路线(Roadmap) | 云 | 工具型 | 轻量&工具型 |
PVM引擎 | × | × | √ |
BPMN2引擎 | √ | √ | √ |
CMMN引擎 | × | √ | × |
DMN引擎 | × | √(开源版支持不太好) | √ |
建模工具选型 | √(AngularJS) | √(AngularJS) | √(Bpmn.js&Camunda Provider) |
建模工具内容 | BPMN2 | BPMN2/CMMN/DMN | BPMN2/CMMN/DMN |
扩展节点(Mule/Http等) | × | √ | √ |
Spring Boot | √ | √ | √ |
Spring Cloud | √ | × | × |
Web控制台 | √ | √ | √ |
Rest接口 | √ | √ | √ |
历史异步归档 | × | √ | × |
异步任务全局锁 | × | √ | × |
- Activiti:Activiti在目前来看有点不思进取,核心功能和内核的优化并没有太大进步,着力点全在商业版和云上面,核心只支持BPMN2协议,跟6版本没有什么区别。如果你是一个老的Activiti使用者,并且只是用BPMN2协议,可以选用Activiti(非Cloud版本)。
- Flowable:Flowable不管是功能层面还是在代码层面来讲,都是这3个中最重的,当初跟Activiti分道扬镳的原因也是因为理念不一样,Flowable更注重其功能性、扩展性和性能。在上面表格中,历史异步归档和异步任务全局锁都是对性能的极大优化,特别是异步任务这一项,当年在使用Activiti的使用是一个极大的困扰,因为异步任务的吞吐反而会随着实例数的增加而加速恶化。Flowable比较臃肿,它支持了太多的东西,以致于如果想做POC或者Demo,环境搭建这一步都够呛。但是如果你本身就想做一个扩展性强的,性能高的工作流平台(SaaS\PaaS),Flowable是不二的选择。
- Camunda:Camunda是这3个里面比较轻量的一个,但是它并没有去掉PVM这个性能较差的流程推动引擎,所以如果你对性能要求很高的话,PVM肯定是不能满足的(Activiti已经在6.X版本的时候放弃了PVM,Flowable亦是如此)。但是Camunda有一个好东西就是它的编辑器,它是基于http://bpmn.io的bpmn.js,cmmn.js,dmn.js来开发的,并且开源了自己的组件库,所以,如果你想做一个轻巧的、灵活的、定制性强的编辑器,工作流是嵌入式的,那么Camunda是一个好选择。
一、Activiti7介绍
官网:activiti.org
1.1 工作流WorkFlow
状态驱动开发(worker->manager)
通过、驳回、转办、加签、传阅、会签
statsu(尽量避免待审核/待处理这样的状态)
0.已创建
1.已提交
2.已部门经理审核
3.已总经理审核
4.审核通过
5.审核拒绝
1.2 Activiti工作流引擎
需求总变 - 痛点产生
Engine工作流引擎
Drools规则引擎
Aviator表达式引擎
解决方案 - 修改配置
1.3 BPMN建模
通过BPMN建模进行描述流程的变更
业务流程模型和符号(Bsiness Process Model And Notation)
通过符号描述一个完整的业务流程
这个图是Activiti里面所支持的,BPMN其实是没有那么详细的
1.3.1 符号类别
事件驱动:Event
任务:Task
流程:ProcessInstance
构建复杂流程(网关):Gateway
子流程:SubProcess
注解:Annotation
1.4 Activiti使用步骤
1.部署activiti:可以理解为一堆Jar包,
2.定义流程:用BPMN定义业务流程
3.部署流程:定义流程是无效的,需要部署之后才能使用
4.启动流程:相当于用户提交业务单据
5.用户代办
6.用户已办
7.流程结束
二、Activit环境搭建
2.1 安装插件
Idea插件actiBPM
idea高于2019需要手动安装
plugins.jetbrains.com/plugin/7429-actibpm/versions
2.2 初始化数据库
- 创建一个maven工程
JDK8或以上,
MySQL5.7或以上(支持h2、MySQL、Oracle、Postgres、DB2、Mssql)
<properties>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<activiti.version>7.1.0.M6</activiti.version>
<activiti.cloud.version>7.0.0.Beta1</activiti.cloud.version>
<mysql.version>8.0.20</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 模型处理 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 转换 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn json数据转换 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 布局 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- activiti 云支持 -->
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>${activiti.cloud.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- 链接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
- 添加activiti的配置文件-头
activiti默认就会使用mysql来创建表。创建时需要先创建一个配置文件
activiti.cfg.xml,来对数据源信息进行定义。
在resources目录下创建activiti.cfg.xml文件。
Ps:
这个目录其实就是classpath下的默认位置。这是activiti默认读取
的目录和文件。
创建在其他目录下也是可以的,但是就需要在生成时指定文件的目录和
名字。
配置文件的基础内容如下: -这里主要是定义几个namespace。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/springbeans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
- 在activiti.cfg.xml中进行配置建表
我们可以在activiti.cfg.xml中添加关于数据库的基础配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/springbeans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 这里可以使用 链接池 dbcp-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"
/>
<property name="url" value="jdbc:mysql://localhost:3306/activiti?
serverTimezone=GMT%2B8" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 引用数据源 上面已经设置好了-->
<property name="dataSource" ref="dataSource" />
<!-- activiti数据库表处理策略 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
PS:
1、processEngineConfiguration这个名字最好不要修改。这是
activiti读取的默认Bean名字。
2、在processEngineConfiguration中也可以直接配置jdbcDriver、
jdbcUrl、jdbcUsername、jdbcPassword几个属性。
3、关于databaseSchemaUpdate这个属性,稍微跟踪一下源码就能看
到他的配置方式:
默认是false;表示不创建数据库,只是检查数据库中的表结构,不满足
就会抛出异常
create-drop:表示在引擎启动时创建表结构,引擎处理结束时删除表结
构。
true:表示创建完整表机构,并在必要时更新表结构。
- 编写java程序生成表
创建一个测试类,调用activiti的工具类,直接生成activiti需要的数据库表。代码如
下:
package com.roy;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.junit.Test;
/**
* @author :楼兰
* @date :Created in 2021/4/7
* @description:
**/
public class TestCreateTable {
/**
* 生成 activiti的数据库表
*/
@Test
public void testCreateDbTable() {
//默认创建方式
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//通用的创建方式,指定配置文件名和Bean名称
// ProcessEngineConfiguration processEngineConfiguration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource
("activiti.cfg.xml", "processEngineConfiguration");
// ProcessEngine processEngine1 = processEngineConfiguration.buildProcessEngine();
System.out.println(processEngine);
}
}
Ps:
注意:从这个代码就能看出我们之前那些默认配置的作用。
ProcessEngines.getDefaultProcessEngine()这行代码默认就会去读取
classpath:下的activiti.cfg.xml和activiti-context.xml两个配置文件。并
且从spring容器中加载名为processEngineConfiguration的Bean。
执行这个脚本就会完成mysql的表结构创建。如果执行正常,可以看到执行了一大
堆的sql语句,最终打印出一行日志
org.activiti.engine.impl.ProcessEngineImpl@77307458
这就表示引擎创建成功了。同时在mysql中可以看到activiti用到的25张表。
这些表机构通常也可以导出成sql文件,然后直接进行移植。但是考虑到
不同版本可能会有微调,所以通常不建议以sql文件的方式移植。
2.3 表结构解读
从这些刚才创建的表中可以看到,activiti的表都以act_开头。第二个部分表示表
的用途。用途也和服务的API对应。
ACT_RE:'RE’表示 repository。 这个前缀的表包含了流程定义和流程静态资源
(图片,规则,等等)。
ACT_RU:'RU’表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异
步任务,等运行中的数据。 Activiti 只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录
。 这样运行时表可以一直很小速度很快。
ACT_HI:'HI’表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任
务等等。
ACT_GE: GE 表示 general。 通用数据, 用于不同场景下
完整的数据库表作用如下:
表分类 | 表名 | 解释 |
---|---|---|
一般数据 | [ACT_GE_BYTEARRAY] [ACT_GE_BYTEARRAY] | 通用的流程定义和流程资源 系统相关属性 |
流程历史记录 | [ACT_HI_ACTINST] [ACT_HI_ATTACHMENT] [ACT_HI_COMMENT] [ACT_HI_DETAIL] [ACT_HI_IDENTITYLINK] [ACT_HI_PROCINST] [ACT_HI_TASKINST] [ACT_HI_VARINST] | 历史的流程实例 历史的流程附件 历史的说明性信息 历史的流程运行中的细节信息 历史的流程运行过程中用户关系 历史的流程实例 历史的任务实例 历史的流程运行中的变量信息 |
流程定义表 | [ACT_RE_DEPLOYMENT] [ACT_RE_MODEL] [ACT_RE_PROCDEF] | 部署单元信息 模型信息 已部署的流程定义 |
运行实例表 | [ACT_RU_EVENT_SUBSCR] [ACT_RU_EXECUTION] ACT_RU_IDENTITYLINK] [ACT_RU_JOB] [ACT_RU_TASK] [ACT_RU_VARIABLE] | 运行时事件 运行时流程执行实例 运行时用户关系信息,存储任务节点与参与者的相关信息 运行时作业 运行时任务 运行时变量表 |
三、Activiti入门
3.1 流程部署
act_re_deployment表
部署成功则生成一条记录
3.2 流程定义
act_re_procdef表
流程id=myLeave:1:4
流程name=员工请假审批流程
流程key=myLeave
流程Version=1
部署ID=1
定义成功则生成一条记录
DEPLOYMENT_ID(流程部署外键)
RESOURCE-NAME(BPMN.xml文件)
DGRM_RESOURCE-NAME(BPMN.png文件)
二进制文件
act_ge_bytearray表
部署的时候存(xml、png)完整BLOB二进制文件直接入库
DEPLOYMENT_ID_(流程部署外键)
Zip上传部署
上传的时候命名要规范图片仅支持png、jpg、gif、svg格式
3.3发起流程
流程定义ID:myLeave:1:4
流程实例ID:2501
当前活动ID:null
3.4 提交申请
流程实例ID:2501
任务id:2505
任务负责人:worker
任务名称:提交请假申请
任务处理
代办任务表
act_ru_task表
将任务从worker提交到manager审核节点
3.5 从manager查询任务
流程实例ID:2501
任务id:5002
任务负责人:manager
任务名称:部门经理审批
3.6 查询历史记录
执行表
act_ru_execution表
_2
StartEvent
myLeave:1:4
2501
<==========>
_3
提交请假申请
myLeave:1:4
2501
<==========>
_4
部门经理审批
myLeave:1:4
2501
<==========>
3.7 流程结束
删除该流程当有审批中的业务默认删除会失败
需要使用级联删除可以完成强制删除
流程变量
act_ru_variable表
Event事件记录
act_evt_log表
Activiti只提供后台,所以只能叫他工作流引擎。
Activiti7操作25张表
四、Activiti进阶
4.1 流程定义域流程实例
流程定义:ProcessDefinition
流程实例:ProcessInstance
流程定义ProcessDefinition是以BPMN文件定义的一个工作流程
每个流程实例之间互补影响
4.1.1 启动流程实例时,添加Businesskey
预留扩展业务代码
流程变量:variables(Map<String,Object> variables)分为Global(针对流程,有重名则覆盖前面的变量值)、Local(针对任务,在本任务变量与Global重名也不影响任务)
租户:tenantId(我们暂时用不到)
Businesskey默认长度255,不要超过255
我们启动一个流程实例的关键代码其实就是这一行
ProcessInstance processInstance = runtimeSewrvice。startProcessInstanceByKey("myLeave");
4.2 网关
4.2.1 排他-网关:ExclusiveGateway
只走其中一条线路
4.2.2 平行-网关:ParallelGateway
每一条线路都要走
4.2.3 包含(相容)-网关:InclusiveGateway(重点)
可选择走其中一条
4.2.4 事件-网关:EventGateway(比较繁琐,基本不用)
4.3 组任务分配
需要候选人在自己的代办列表进行认领,认领后候选人升级为责任人,其他候选人无此任务代办,责任人可退还任务或者转办任务,该任务节点所有候选人可以在代办进行认领,管理员可在本任务节点任何状态下指派任务
分配多个候选人,本节点任何一个候选人完成,任务往下一个任务节点走