前言,因项目使用JDK8,而flowable-ui在7.0.0后移除并最低需要SpringBoot3,JDK17,故学习使用选择6.8.0版本
以下来自git官方描述
This is the first milestone for version 7 of the Flowable Engines focusing on the Spring Boot 3, Spring 6 and Java 17 upgrade.
1. 第一步切换到mysql数据库,并启动flowable-ui
用解压缩软件打开flowable-ui.war,可见\WEB-INF\classes\下有一个flowable-default.properties文件,修改其中的database
2.移入mysql连接jar包
移入\WEB-INF\lib\目录下
jar -xvf flowable-ui.war
创建tmp临时文件夹,把解压项三个目录拉进去,cd进tmp,并执行
jar -cfM0 flowable-mysql-ui.jar ./
参考 https://www.cnblogs.com/zjfjava/p/16943736.html
3.启动jar
直接执行如下命令
java -jar flowable-mysql-ui.jar
访问 http://localhost:8080/flowable-ui/idm/#/login
- 数据库连接增加:nullCatalogMeansCurrent=true
如下图中的workflow(否则无法自动生成新表)
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://github.com/baomidou/dynamic-datasource-spring-boot-starter
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: true
# 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭
seata: false
# 严格模式 匹配不到数据源则报错
strict: true
primary: master
datasource:
master:
url: jdbc:mysql://192.168.1.25:3306/sup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
workflow:
url: jdbc:mysql://192.168.1.25:3306/workflow2?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
- 配置动态数据源所使用的ds名称
# 工作流 Flowable 配置
flowable:
# 1. false: 默认值,Flowable 启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
# 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
# 3. create_drop: 启动时自动创建表,关闭时自动删除表
# 4. drop_create: 启动时,删除旧表,再创建新表
database-schema-update: true # 设置为 false,可通过 https://github.com/flowable/flowable-sql 初始化
ds: workflow # ds名称,否则默认为master
db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置
check-process-definitions: false # 设置为 false,禁用 /resources/processes 自动部署 BPMN XML 流程
history-level: full # full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
学习文档: https://blog.csdn.net/zhaozhiqiang1981/article/details/129240406
https://blog.thatcoder.cn/wiki/YuDaoCloud/工作流手册/工作流(Flowable)会签、或签/工作流(Flowable)会签、或签.html
- flowable中的service
- ProcessEngineConfiguration类通过读取xml文件配置流程引擎。
- 从ProcessEngine类中可以得到各种服务,值得注意的是,这些服务可以被认为是单例模式。
- RepositoryService是使用Flowable引擎时需要的第一个服务,它提供用于管理和操作部署和流程定义(BPMN )的操作,主要负责一些静态的配置。
- RuntimeService主要负责一些动态的任务,如启动一个新的实例,通常一个流程可以对应多个实例。它也用于检索和储存一些流程变量,比如在单向网关组件中需要传递之前的选择。
- TaskService主要和分配给人的任务相关,比如将任务分配给用户。
- IdentityService主要负责用户的管理。
- FormService是一个可选的服务,主要负责开始表单和结束表单。
- HistoryService保存历史信息。
- DynamicBpmnService可以动态的添加新的流程。
Starter | 描述 |
---|---|
flowable-spring-boot-starter-cmmn | 提供以独立运行模式启动CMMN引擎的依赖 |
flowable-spring-boot-starter-cmmn-rest | 提供以独立运行模式启动CMMN引擎,并提供其REST API的依赖。 |
flowable-spring-boot-starter-dmn | 提供以独立运行模式启动DMN引擎的依赖。 |
flowable-spring-boot-starter-dmn-rest | 提供以独立运行模式启动DMN引擎,并提供其REST API的依赖。 |
flowable-spring-boot-starter-process | 提供以独立运行模式启动流程引擎的依赖。 |
flowable-spring-boot-starter-process-rest | 提供以独立运行模式启动流程引擎,并提供其REST API的依赖。 |
flowable-spring-boot-starter | 提供启动所有Flowable引擎(流程,CMMN,DMN,Form,Content及IDM)的依赖。 |
flowable-spring-boot-starter-rest | 提供启动所有Flowable引擎,并提供其REST API的依赖。 |
flowable-spring-boot-starter-actuator | 提供Spring Boot Actuator所需的依赖。 |
-
表结构简介
1、Flowable的所有数据库表都以ACT_开头。第二部分是说明表用途的两字符标示符。服务API的命名也大略符合这个规则。
2、ACT_RE_: 'RE’代表repository。带有这个前缀的表包含“静态”信息,例如流程定义与流程资源(图片、规则等)。
3、ACT_RU_: 'RU’代表runtime。这些表存储运行时信息,例如流程实例(process instance)、用户任务(user task)、变量(variable)、作业(job)等。Flowable只在流程实例运行中保存运行时数据,并在流程实例结束时删除记录。这样保证运行时表小和快。
4、ACT_HI_: 'HI’代表history。这些表存储历史数据,例如已完成的流程实例、变量、任务等。
5、ACT_GE_: “GE”代表“General”(通用),通用数据。在多处使用。 -
流程写表
// 保存流程模型
repositoryService.saveModel(newModel);
保存模型后会写入以下表
ACT_RE_MODEL中新增一条记录.
ACT_GE_BYTEARRAY 流程模型内容表 记录流程定义的资源信息,xml和流程图图片信息
设计好的流程通过下面语句保存在act_ge_bytearray表中,id作为act_re_model的外键EDITOR_SOURCE_VALUE_ID存放
# /model/deploy
// 创建 Deployment 部署
Deployment deploy = repositoryService.createDeployment()
.key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
.addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
.deploy();
Model Deploy后会写入以下表
ACT_RE_DEPLOYMENT 流程部署表 记录这次部署行为
ACT_RE_PROCDEF 流程定义表 记录这次部署动作对应的流程定义信息
以部署一个自定义key为bpmkey为例,则id为bpmkey:1:168b6133-efeb-11ee-8e18-005056c00008 ,{key}:{version}:{随机id},
所以启动流程时,优先选择使用id。
# /process-instance/create
// 创建流程实例
ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
.processDefinitionId(definition.getId())
.businessKey(businessKey)
.name(definition.getName().trim())
.variables(variables)
.start();
新建流程实例后会以下表
act_ru_task 运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用
act_ru_execution 运行时流程执行实例表,记录运行中流程运行的各个分支信息
(当没有子流程时,其数据与act_ru_task表数据是一一对应的)
act_hi_procinst 每启动一个流程实例会在该表中维护一条历史记录
审批操作
# /task/approve
// 完成任务,审批通过
taskService.complete(task.getId(), instance.getProcessVariables());
# /task/reject
// 更新流程实例为不通过
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason());
complete(String taskId, Map<String, Object> variables)
该方法实现变量用户组审批功能
Map<String, Object> variables = new HashMap<>();
variables.put("myAssigneId", "list");
taskService.complete(task.getId(),variables);
流程定义和流程实例的关系:
- 流程定义:java中的类
- 流程实例:java中根据流程定义类实例化出的对象
tips:
// 挂起
repositoryService.suspendProcessDefinitionById(id, false, null);
挂起流程定义,不影响之前已经提交的流程实例,而之后无法使用改流程定义开启新的流程实例。
- 全局变量和局部变量
https://blog.csdn.net/bluede2015/article/details/130009751
setVariable为全局变量
setVariableLocal为局部变量
创建变量写入act_ru_variable表,流程结束后变量记录会自动清空并写入act_hi_varinst表
任务监听器的概念
在创建,分配,完成或者删除时触发
- 都有哪几个重要字段
①procInstId 流程实例Id
②taskId 任务Id
③executionId 执行Id
④processDefinitionId 流程定义Id
⑤processDefinitionKey 流程定义Key
⑥processDefinitionName 流程定义名称
总结一下,如果形象的拿procInstId,executionId,taskId做一个比喻的话,procInstId为一个面,executionId为在面上的一条线,taskId为在线上的一个点。
- 候选人的概念
候选人不是审批人,候选人需要通过拾取的操作变成审批人
多个候选人,只有一个可以变成审批人( 通过拾取)
审批人如何不想审批了,可以归还。 从审批人->候选人
//查询候选人为张三的代办信息
List<Task> taskList = taskService.createTaskQuery().taskCandidateUser("zhangsan").list();
for (Task task : taskList) {
System.out.println("task = " + task);
//拾取 zhangsan 候选人-> 审批人
taskService.claim(task1.getId(),"zhangsan");
// 归还 zhangsan 审批人 -> 候选人
taskService.unclaim(task1.getId());
}
审批人想他人帮忙做审批,则可以做指派动作
//指派
taskService.setAssignee(task.getId(),"zhangsan");
评论区