flowable
1. 概念
-
模型 Model
-
流程定义
类似一个java类,可以创建多个流程实例。 -
流程部署
-
流程实例
类似Java new 出来的对象,一个流程定义可以发起n个不同的流程实例。 -
执行id
可以理解为流程实例更小的流程单元,2个并行网关,就对应者一个流程实例id,2个执行id(每条子线的id) -
活动 Activity
实例的发起,任务,网关,都是活动。 -
任务 Task
一个待办,就是一个任务。
2. 对比总结
wps搜:流程引擎flowable表解读
3. 表、字段相关含义
-
详细介绍:
https://blog.csdn.net/weixin_44192363/article/details/132037642?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171031304316800226565841%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171031304316800226565841&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-1-132037642-null-null.142v99control&utm_term=flowable%E8%A1%A8%E5%AD%97%E6%AE%B5%E5%90%AB%E4%B9%89&spm=1018.2226.3001.4187 -
ru_
只记录流程实例未结束的数据,一旦流程实例结束,则包含ru_的表都没有该实例数据。
4. yml配置项解读
4.1. flowable.history-level
有4个值,记录范围从小到大:none > activity > audit > full
4.1.1. none
- 含义:不记录任何历史数据。这是性能最优的选项,因为它避免了历史数据的存储和处理开销。但是,这种模式下,无法获取工作流实例的历史信息,如流程的启动时间、结束时间、任务的完成时间等。
- 适用场景:适用于对历史数据没有需求,并且希望最大程度提高性能的场景,例如一些简单的、临时的工作流,或者对性能要求极高且历史数据无关紧要的流程。
4.1.2. activity
- 含义:记录活动(Activity)级别的历史数据。它会记录流程实例中每个活动(如任务、网关等) 的开始和结束时间等基本信息。这样可以追踪流程中每个步骤的执行时间,但不会记录详细的变量变化等信息。
- 适用场景:适用于需要大致了解流程执行步骤的时间信息,用于简单的流程监控和性能分析。例如,在一个简单的请假流程中,可以知道每个审批任务的开始和结束时间,从而统计每个环节的耗时。
4.1.3. audit
- 含义:除了活动级别的历史数据外,还会记录流程变量的更新情况。这提供了更详细的历史信息,包括流程在执行过程中变量是如何变化的。这样可以更好地进行流程审计,了解流程的详细执行情况。
- 适用场景:适用于需要对流程进行详细审计的场景,例如财务审批流程,需要追踪金额等变量的变化情况,以及流程步骤的执行时间,以确保流程的合规性和准确性。
4.1.4. full
- 含义:记录最完整的历史数据,包括所有的活动信息、变量变化、表单属性等。这提供了关于流程执行的最全面的历史记录,但会产生最多的存储开销和一定的性能影响。
- 适用场景:适用于对流程执行历史有严格的追溯和分析需求的场景,例如在复杂的业务流程中,需要详细分析每个流程实例的所有细节,包括用户操作、变量变化等所有信息,用于故障排查、业务优化等复杂场景。
5. 问题
5.1. 查模型当前激活的流程版本(定义)
-
可通过部署id查询。
发布部署时,得保证模型的部署id是最新流程定义的部署id,且该部署id对应的流程定义状态=1。
act_re_deployment 流程部署表
act_re_model表DEPLOYMENT_ID_可以存激活的部署id,act_re_procdef 表也会存部署id。 -
通过模型key + 状态 + 版本号
流程定义的key就是模型的key,act_re_procdef表SUSPENSION_STATE_ = 1代表激活,vesion最大的,就是某个模型当前最新的激活版本。
5.2. 模型部署时是否自动生成流程定义?
是的。
flowable在模型部署时,核心是部署bpm.xml,act_ge_bytearray表也有部署id。
5.3. 如何生成一个流程定义?
- 前置条件:1:得有bpm.xml流程图;2:得通过部署产生;
- repositoryService负责
- 通过创建部署,自动生成的定义。
- 定义的category 2家都是分2步设置,难道不能创建时就设置?
// 芋道 的用法
// 基于模型,部署
Deployment deploy = repositoryService.createDeployment()
.key(model.getKey()).name(model.getName()).category(model.getCategory())
.addBytes(model.getKey() + BpmnModelConstants.BPMN_FILE_SUFFIX, bpmnBytes)
.tenantId(FlowableUtils.getTenantId())
.disableSchemaValidation() // 禁用 XML Schema 验证,因为有自定义的属性
.deploy();
// 设置 ProcessDefinition 的 category 分类
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploy.getId()).singleResult();
repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory());
// ruoyi-flowable 的用法
// 没有用模型,直接用xml部署
Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy();
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
repositoryService.setProcessDefinitionCategory(definition.getId(), category);
5.4. 如何生成一个流程实例?
- 流程实例依赖流程定义,流程定义又依赖于bpm.xml文件的部署。所以act_ge_bytearray文件表得有数据,act_re_deployment 流程部署表得有部署id, act_re_procdef 定义表得有数据。
- 最好在检查状态是否已激活。同一个key,是否有多个激活,最好保证只有一个激活。
- 确定好发起人
- runtimeService 负责
// 芋道 的用法
ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
.processDefinitionId(definition.getId())
.businessKey(businessKey)
.name(definition.getName().trim())
.variables(variables)
.start();
// ruoyi-flowable 的用法(流程定义和变量map)
ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
// 流程定义id 、businessKey 、变量map
runtimeService.startProcessInstanceById("流程定义id","businessKey", variables);
5.5. yudao生成流程实例前校验了些什么?
- 详情见 BpmProcessInstanceServiceImpl.createProcessInstance0()方法
5.6. 执行监听器和任务监听器有什么区别
-
事件类型不同
start,end,take
create,assignment,complete,delete -
执行监听器
针对流程实例,对流程实例启动和结束做增强。
流程结束,可以执行一些业务处理,如将业务数据同步给三方系统。 -
任务监听器
针对任务创建、指派、完成和删除等做增强。
5.7. 流程实例创建、结束,如何执行回调函数?
-
可以用执行监听器
-
可以继承AbstractFlowableEngineEventListener,重新相应方法,处理自己的业务。
5.8. 如何打印flowable的sql
- 以MyBatis为例
yml文件
logging:
level:
org.flowable: DEBUG
5.9. task完成后,是如何指定审批人的?
5.10. 如何确定节点审批人
5.10.1. 流程表达式
5.10.1.1. 利用反射
- ui设计器:
${bpmTaskAssignLeaderExpression.calculateUsers(execution, 1)}
- java端
通过DelegateExecution获取流程实例,
@Component
public class BpmTaskAssignLeaderExpression {
public Set<Long> calculateUsers(DelegateExecution execution, int level) {
Assert.isTrue(level > 0, "level 必须大于 0");
// 获得发起人
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
// 获得对应 leve 的部门
DeptRespDTO dept = null;
for (int i = 0; i < level; i++) {
// 获得 level 对应的部门
if (dept == null) {
dept = getStartUserDept(startUserId);
if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
return emptySet();
}
} else {
DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
break;
}
dept = parentDept;
}
}
return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
}
}
5.11. 如何实现会签
5.11.1. 用户任务-多实例
-
3根线的 含义
竖线:并行(parallel),用户任务ru_task表会为所有用户同时生成待办数据。
横线:串行(sequential),ru_task表只会有一条,a,b,c依次complete后,下个用户才会生成待办信息。 -
第一个待办节点使用示例(流程发起时,为下一个用户任务确定待办人)
1:ui配置
![img]()
![img]()
2:代码map传参
![img]()
5.12. 如何实现多人或签
- 基于上面【如何实现会签】,再加一个条件
5.12.1. 条件表达式
涉及3个变量
nrOfInstances: 实例总数。
nrOfActiveInstances: 当前活动的(未完成)实例,对于一个连续的多实例,这将永远是1。
nrOfCompletedInstances: 已经完成的实例数。
- 基于上面3个变量,可以灵活实现:1人或签,半数通过,n/m通过。
![img]()
5.12.2. 基于java代码
-
实际是把uel表达式,改为java代码
-
1:编写java代码
![img]()
-
2:ui填写uel表达式
![img]()
6. 流程梳理
6.1. 部署(发布)表之间发生了什么
-
前置条件
得有xml流程图文件及bpm.xml -
有模型表参与
![image]()
-
无模型表参与
![image]()
6.2. 发起流程(生成流程实例)发生了什么
6.3. 流程实例结束发生了什么
- 包含ru_的表,将清除该流程实例相关数据!!
7. Flowable-ui
7.1. docker运行
- 运行命令
docker run -p 8080:8080 镜像id
- 访问地址:http://localhost:8080/flowable-ui
- 登录账号
user: admin
password: test
8. 监听器
8.1. 执行监听器
- 作用域
开始、结束事件,顺序箭头,任务。 - 作用效果
不管是圆圈,箭头,方形任务,此活动activity,开始和结束,就会执行其中的执行监听器。
![img]()
8.2. xml内容

8.2.1. 事件类型
-
start开始事件
-
take执行事件
-
end结束事件
8.2.2. 监听器类型
- 类
需要实现ExecutionListener
不用注入到Spring的bean容器
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.execution;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
/**
* OA流程结束-执行监听器
* @author JiangFeng
* @since 2025/2/10
*/
public class OALeaveFlowEndExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) {
System.out.println("执行监听器,触发了。。。");
}
}

-
表达式
必须注入到Spring的bean容器
参数固定带上 DelegateExecution execution -
事件类型










浙公网安备 33010602011771号