Flowable介绍:
Flowable 是一个轻量级的业务流程管理(BPM)和工作流引擎,它允许开发者在应用程序中定义、执行和管理业务流程。简单来说,它帮助你自动化和协调一系列任务或步骤,以完成某个业务目标。
举个生活中的例子:
想象你在公司申请一个请假流程:
- 员工提交请假申请
- 上级审批;如果超过3天,还需要更高级别的领导审批
- 审批通过后,HR系统更新假期记录
- 最后员工收到审批结果通知
这个过程可以使用 Flowable 来建模和自动化执行。
Flowable 类似生活中的:快递分拣系统
你可以把它想象成一个自动化的快递分拣流水线:
- 快递到达仓库(触发流程)
- 扫描包裹(第一个节点)
- 根据目的地决定流向(条件分支)
- 打包、装车、运输(多个处理节点)
- 到达目的地网点(结束事件)
在这个过程中,Flowable 就像那个智能的“分拣系统”,根据预设规则把任务一步步流转下去。
Flowable 的核心概念类比:
ProcessDefinition:分拣系统的图纸/流程图
ProcessInstance:正在运行的一个快递包裹流程
Task:某个分拣节点需要做的操作(如扫描、打包)
UserTask:需要人工参与的操作(如客服确认地址)
ServiceTask:自动执行的任务(如系统自动发送短信)
Gateway:分岔路口,根据条件选择不同路线(如包裹大小决定走哪个通道)
总结一句话:
Flowable 就像是一个“流程指挥官”,帮你把一堆杂乱的业务步骤有条不紊地组织起来,让系统知道什么时候该做什么事。
接下来的流程需要你提前了解如何通过Flowable UI画一个完整的流程图,并且配置好对应的参数变量,或者了解bpmn20.xml文件的结构。其实Flowable流程图导出就是一个bpmn20.xml
下面是我在写Demo过程中使用的流程图及bpmn20.xml

bpmn20.xml文件内容
公司员工请假申请流程
是否大于3天
结束
<=3天
>3天
3}]]>
驳回
通过
驳回
通过
自行将改代码保存成以bpmn20.xml为文件后缀的文件,比如【公司员工请假申请流程.bpmn20.xml】注意不可以是【公司员工请假申请流程.bpmn20(1).xml】
接下来就是上代码:
前提:需要创建好flowable数据库,具体我在上一篇Flowable UI已经讲过
创建一个SpringBoot项目
pom.xml文件引入如下依赖
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
1.18.34
mysql
mysql-connector-java
org.flowable
flowable-spring-boot-starter
6.7.2
cn.hutool
hutool-all
5.8.22
yml文件配置好数据源

操作流程定义(ProcessDefinition)(增删改查)
@RestController
@RequestMapping("/processDefinition")
public class ProcessDefinitionController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngine processEngine;
/**
* 上传一个xml文件,创建一个或多个流程定义(一个xml文件可能有多个流程图)
*/
@PostMapping("/deploy")
public String deploy(@RequestParam("file") MultipartFile file,@RequestPart ProcessDeployAddReq dto) {
try {
String xmlContent = new String(file.getBytes(), StandardCharsets.UTF_8);
Deployment deployment = repositoryService.createDeployment()
.addString(dto.getProcDefCode() + ".bpmn", xmlContent)
.key(dto.getProcDefCode())
.name(dto.getProcDefName())
.deploy();
return deployment.getId();
} catch (IOException e) {
throw new RuntimeException("文件读取失败", e);
}
}
/**
* 获取所有流程定义列表
* @return
*/
@GetMapping("/processList")
public List
注意区分Deployment 和ProcessDefinition
Deployment 表示一次部署,一次部署可能会包含多个流程定义,即一个xml文件可能有多个流程图
特点:
- 每次调用repositoryService.createDeployment().deploy()都会产生一个新的 Deployment。
- 可以包含多个流程定义(一个 BPMN 文件中可能定义多个 )。
- 主要用于管理和查询流程资源的部署记录。
ProcessDefinition 描述一个流程定义,即一个流程图
特点:
- 来源于 BPMN 文件中的 定义。
- 每个流程定义都有版本号,相同 key 的流程定义多次部署会递增版本。
- 是流程引擎运行时的核心数据结构。
获取流程图图片时会出现中文乱码的情况,可以配置好字体,我这使用的是全局
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer {
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName("宋体");
engineConfiguration.setLabelFontName("宋体");
engineConfiguration.setAnnotationFontName("宋体");
}
}
操作流程实例ProcessInstance
@RestController
@RequestMapping("/processInstance")
public class ProcessInstanceController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private HistoryService historyService;
/**
* 获取流程实例列表
* @return
*/
@RequestMapping("/list")
public List
注意:
1、流程实例参数的获取
在 Flowable 中,ProcessInstance 接口的 getProcessVariables() 方法默认不会返回流程变量,除非你在查询时显式指定需要加载变量。这是出于性能考虑:流程变量可能较大,因此默认不主动加载
需要在查询的时候
runtimeService.createProcessInstanceQuery()
.includeProcessVariables() // ⚠️ 关键点:包含流程变量
.list()
2、ProcessInstance对象不能直接响应给前端
因为ProcessInstance没有序列化
3、ProcessInstance对象不能通过BeanUtil.beanToMap()
ProcessInstance 对象,它是一个代理对象。当你使用 Hutool 的 BeanUtil.beanToMap() 方法进行转换时,会尝试访问所有属性,包括一些延迟加载或需要 CommandContext 支持的属性(比如当前节点、流程模型等),从而触发如下异常:

任务操作
用户任务操作
这里操作的用户任务是流程实例还未结束的任务,已经结束的在下面介绍的历史里面
@RestController
@RequestMapping("/task")
public class TaskController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
/**
*获取任务列表,注意这里获取到的只是还未结束的流程实例的任务列表
*
*/
@RequestMapping("/list")
public List
服务任务
服务任务是自动执行的,在xml文件里面通过class配置了对应的执行类
执行类需要实现JavaDelegate重写execute方法,在execute方法里面编写业务逻辑代码
public class YesJavaDelegateImpl implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println(delegateExecution.getVariables());
System.out.println(delegateExecution.getProcessInstanceId());
System.out.println("通过申请");
// 修改申请状态为通过
//给申请人发送消息
System.out.println("给申请人发送消息");
}
}
历史节点信息
下面只是几个简单的,其他自行扩展
/**
* 流程实例已经结束的节点信息
* @author yzz
*/
@RestController
@RequestMapping("/history")
public class HistoryController {
@Autowired
private HistoryService historyService;
/**
*
*获取历史流程实例,已经结束的
*/
@RequestMapping("/list")
public List