Flowable基础篇
课程环境说明:
- JDK8
- Flowable6.7.2
- MySQL8
一、基础知识科普
1.工作流发展
BPM(BusinessProcessManagement),业务流程管理是一种管理原则,通常也可以代指BPMS(BusinessProcessManagementSuite),是一个实现整合不同系统和数据的流程管理软件套件.
BPMN(BusinessProcessModelandNotation)是基于流程图的通用可视化标准。该流程图被设计用于创建业务流程操作的图形化模型。业务流程模型就是图形化对象的网状图,包括活动和用于定义这些活动执行顺序的流程设计器
。BPMN2.0正式版本于2011年1月3日发布,常见的工作流引擎
如:Activiti、Flowable、jBPM 都基于 BPMN 2.0 标准。
然后来看看BPM的发展历程:
说明:最新版本的Flowable7.0.0需要的环境:https://tkjohn.github.io/flowable-userguide/#download
- SpringBoot3
- Spring6
- Java 17
2.流程设计器
2.1 误区说明
为什么一定要纠结于找IDEA中安装绘制的插件呢?我们需要的是一个能够帮助我们绘制流程图的工具。即使没有流程设计器我们也可以通过代码来定义流程的。
2.2 古老的Eclipse
在Eclipse中我们可以通过安装插件来绘制流程图。然后导出对应的bpmn
文件。然后就可以做相关的部署操作了。
这个只做简单介绍,了解即可。
2.3 官方的FlowableUI
Flowable官方给我们提供了一个功能完备的基于web应用的流程设计器。可以用于流程相关的操作。具体提供了如下的功能:
- Flowable IDM: 身份管理应用。为所有Flowable UI应用提供单点登录认证功能,并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能。
- Flowable Modeler: 让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。
- Flowable Task: 运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务,以及查询流程实例与任务的功能。
- Flowable Admin: 管理应用。让具有管理员权限的用户可以查询BPMN、DMN、Form及Content引擎,并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过REST API连接至引擎,并与Flowable Task应用及Flowable REST应用一同部署。
所有其他的应用都需要Flowable IDM提供认证。每个应用的WAR文件可以部署在相同的servlet容器(如Apache Tomcat)中,也可以部署在不同的容器中。由于每个应用使用相同的cookie进行认证,因此应用需要运行在相同的域名下。
2.4 BPMN.js自定义
FlowableUI是官方提供的,针对国内复杂的流程业务需求有时并不能很好的满足企业的工作流的需求。这时我们就可以基于bpmn.js
来自定义流程设计器,官网地址:https://bpmn.io/toolkit/bpmn-js/walkthrough/
开源的学习资料:https://github.com/LinDaiDai/bpmn-chinese-document/tree/master/LinDaiDai
2.5 第三方的设计器
如何感觉完全基于bpmn.js
来从零开发一个流程设计器太费时了。也可以找一些开源的别人写好的流程设计器比如:
- https://gitee.com/zhangjinlibra/workflow-engine?_from=gitee_search
- https://gitee.com/MiyueSC/bpmn-process-designer?_from=gitee_search
- 其他的可以自行在GitHub或者gitee上查找
最后我们可以不借助流程设计器来定义流程图。我们可以通过BpmnModle对象来自定义流程图
二、流程审批初体验
1.FlowableUI安装
官方提供的FlowableUI是集成在Flowable源码包中的。但是在最新的7.0.0
中已经移除了。我们需要在6.7.2
中获取。
https://github.com/flowable/flowable-engine/releases
对应的流程设计器在如下目录中:
然后我们把这个flowable-ui.war
扔到Tomcat容器中然后启动Tomcat服务即可:不要部署在有中文的目录下!!!
访问地址:http://localhost:8080/flowable-ui
登录成功的效果
2.用户管理
流程审批是伴随着用户
的审批处理的。所以肯定需要用户的参与。我们先通过身份管理应用程序
来创建两个测试的用户。
点击进入后可以看到在FlowableUI中针对用户这块是从三个维度来管理的
- 用户
- 组
- 权限控制
我们先就创建普通的用户。并分配相关的权限
创建了zhangsan
并设置了密码为123
.然后分配相关的权限
然后我们就可以通过zhangsan
来登录,然后就可以看到相关的功能权限。
同样的操作我们再创建下lisi
的账号。
3.流程定义
有了相关的用户信息。我们就可以来创建流程图了。这块我们需要通过建模应用程序
来实现。
点击后进入,看到如下的界面:
第一次进入提示我们还没有创建流程模型,我们可以点击右上角的创建流程
按钮开始创建第一个流程案例。
然后会进入到具体的流程图的绘制界面。
创建第一个请假流程图
然后我们需要分配相关节点的审批人
- 人事审批-- zhangsan 审批
- 经理审批 – lisi 审批
分配操作
选择分配给单个用户
并搜索到zhangsan
.
相同的操作完成经理审批
节点的配置,然后就可以保存退出了
到此流程定义完成~
4.图标介绍
BPMN 2.0是业务流程建模符号2.0的缩写。它由Business Process Management Initiative这个非营利协会创建并不断发展。作为一种标识,BPMN 2.0是使用一些符号来明确业务流程设计流程图的一整套符号规范,它能增进业务建模时的沟通效率。目前BPMN2.0是最新的版本,它用于在BPM上下文中进行布局和可视化的沟通。接下来我们先来了解在流程设计中常见的 符号。
BPMN2.0的基本符合主要包含:
4.1 事件图标
在Flowable中的事件图标启动事件,边界事件,中间事件和结束事件.
4.2 活动(任务)图标
活动是工作或任务的一个通用术语。一个活动可以是一个任务,还可以是一个当前流程的子处理流程; 其次,你还可以为活动指定不同的类型。常见活动如下:
4.3 结构图标
结构图标可以看做是整个流程活动的结构,一个流程中可以包括子流程。常见的结构有:
4.4 网关图标
网关用来处理决策,有几种常用网关需要了解:
5.流程部署
有了流程定义后然后我们可以通过FlowableUI中提供的应用程序
我们可以来完成部署的相关操作。
进入功能页面后我们可以创建应用程序
。
然后在弹出的菜单中录入基本信息
点击选择需要绑定的流程定义
点击进入后我们可以点击右上角的发布
操作来完成部署的行为:
部署出现的时候出现了异常信息:
同时在看控制台出现了如下的问题
原因是部署的项目不能放在有中文的路径下。所以我们调整下Tomcat
的位置.然后再启动即可,然后在发布就提示发布成功了
6.流程审批
流程部署完毕后我们就可以启动一个流程实例了。然后就可以走流程审批的操作。启动流程实例我们通过任务应用程序
来处理。
点击启动新的流程
启动流程后进入到人事审批
的阶段
点击显示流程
可以看到当前的状态
然后我们可以切换到zhangsan
账号登录后来审批操作
点击完成后,点击流程
可以看到对应的流程情况
然后切换到lisi
登录来继续审批
点击完成
后,审批操作完成。到此FlowableUI的流程审批操作就演示完成。
三、流程审批操作
1.案例环境
创建一个基本的SpringBoot项目。相关的版本如下:
- SpringBoot2.6.13
- JDK8
- Flowable6.7.2
对应的依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--Flowable的核心依赖-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.2</version>
</dependency>
<!-- MySQL的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.14</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- 日志相关 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
2.流程部署
流程部署我们可以在Spring的环境下部署。也可以在非Spring的环境下部署。下面先展示非Spring环境下的部署操作:
/**
* 不通过Spring容器。我们单独的构建ProcessEngine对象来实现部署的操作
*/
@Test
void contextLoads() {
// 1.流程引擎的配置
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
.setJdbcUsername("root")
.setJdbcPassword("123456")
.setJdbcDriver("com.mysql.cj.jdbc.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 2.构建流程引擎对象
ProcessEngine processEngine = cfg.buildProcessEngine();
System.out.println(processEngine);
Deployment deploy = processEngine.getRepositoryService().createDeployment()
.addClasspathResource("process/HolidayDemo1.bpmn20.xml")
.name("第一个流程案例")
.deploy();
System.out.println(deploy.getId());
}
方法执行成功后会在这三张表中记录相关的部署信息
- act_ge_bytearray:记录流程定义的资源信息。xml和流程图的图片信息
- act_re_deployment:流程部署表,记录这次的部署行为
- act_re_procdef:流程定义表,记录这次部署动作对应的流程定义信息
databaseSchemaUpdate:用于设置流程引擎启动关闭时使用的数据库表结构控制策略
false
(默认): 当引擎启动时,检查数据库表结构的版本是否匹配库文件版本。版本不匹配时抛出异常。true
: 构建引擎时,检查并在需要时更新表结构。表结构不存在则会创建。create-drop
: 引擎创建时创建表结构,并在引擎关闭时删除表结构。
注意
:要注意区分流程部署和流程定义的关系
- 一次部署操作可以部署多个流程定义
// 2.构建流程引擎对象
ProcessEngine processEngine = cfg.buildProcessEngine();
System.out.println(processEngine);
Deployment deploy = processEngine.getRepositoryService().createDeployment()
.addClasspathResource("process/HolidayDemo1.bpmn20.xml") // 部署一个流程
.addClasspathResource("process/消息中间事件.bpmn20.xml") // 部署第二个流程
.name("第一个流程案例")
.deploy();
当然上面的操作我们是自己定义ProcessEngine
和ProcessEngineConfiguration
来实现流程引擎对象的获取操作,我们完全可以把这些初始化的操作交给Spring容器来管理。接下来我们看看在SpringBoot项目中怎么简化处理。首先依赖我们上面已经添加了。然后需要在application.yml
中配置如下信息:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true
username: root
password: 123456
hikari:
minimum-idle: 5
idle-timeout: 600000
maximum-pool-size: 10
auto-commit: true
pool-name: MyHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
flowable:
async-executor-activate: true #关闭定时任务JOB
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
database-schema-update: true
server:
port: 8082
logging:
level:
org:
flowable: debug
注意在url中需要添加nullCatalogMeansCurrent=true
属性。不然启动服务的时候会出现如下问题
具体部署流程的代码,就可以直接从Spring容器中获取ProcessEngine
对象了。大大简化了相关的代码
@Autowired
private ProcessEngine processEngine;
/**
* 流程部署
*/
@Test
public void deployFlow(){
Deployment deploy = processEngine.getRepositoryService().createDeployment()
// 部署一个流程
.addClasspathResource("process/HolidayUI.bpmn20.xml")
// 部署第二个流程
//.addClasspathResource("process/消息中间事件.bpmn20.xml")
.name("第一个流程案例")
.deploy();
System.out.println(deploy.getId());
}
3.启动流程实例
流程部署完成后我们就可以发起一个流程实例。具体的操作如下:
/**
* 发起流程
*/
@Test
public void startProcess(){
// 发起流程需要通过RuntimeService来实现
RuntimeService runtimeService = processEngine.getRuntimeService();
//对应act_re_procdef的id,流程定义之后会生成id , key对应KEY
// 一、流程实例id启动流程实例
String processInstanceId = "HolidayUI:1:c8fa0f40-71a8-11ef-b3f4-287fcff7031e";
runtimeService.startProcessInstanceById(processInstanceId);
// 二、指定流程定义key启动流程实例 ,key对应定义流程时指定的key: HolidayUI
//runtimeService.startProcessInstanceByKey("HolidayUI");
//runtimeService.startProcessInstanceByKeyAndTenantId()
}
启动流程需要通过RuntimeService
来实现。同时在启动流程的时候有两个方法可以调用:
- startProcessInstanceById: 对应于act_re_procdef 表中的id
- startProcessInstanceByKey: 对应于act_re_procdef 表中的key
启动流程后根据我们的定义。流程会走到人事审批
。
这时我们可以在act_ru_task
表中看到对应的记录。act_ru_task
记录的都是当前待办的记录信息
还有一个要注意的:每启动一个流程实例那么就会在act_hi_procinst
表中维护一条记录。然后在act_ru_execution
会记录流程的分支
流程定义和流程实例的关系:
- 流程定义:Java中的类
- 流程实例:Java中的对象
4.流程审批
流程启动后会进入到相关的审批节点。上面的案例中就会进入到人事审批
节点。审批人是zhangsan
,也就是zhangsan
有了一条待办信息。这时候我们可以查询下zhangsan
有哪些待办任务。
/**
* 待办任务查询
*/
@Test
void findTask(){
// 任务查询这块我们可以通过 TaskService 来实现
TaskService taskService = processEngine.getTaskService();
// 查询的其实就是 act_ru_task 中的记录
List<Task> list = taskService.createTaskQuery()
.taskAssignee("zhangsan") // 根据审批人来查询
.list();// 返回多条记录
for (Task task : list) {
System.out.println(task.getId());
}
}
查询出了对应的两条记录
找到了需要审批的任务。我们就可以根据 taskId
来完成审批的操作
/**
* 完成任务的审批
*/