声明:本文只是使用flowable一个小demo,仅用作个人笔记和抛转引玉用,生产中请根据项目需要作相应调整!!!
先上订单审批的工作流程图

简要介绍下上面的工作流:
1、开始节点,客户填写订单;
2、使用排他网关判断订单金额,如果订单金额<=10万,则直接创建订单,流程结束;
3、如果订单金额超过10万,则自动发送邮件抄送,然后需人工介入处理,经理进行确认;
4、经理确认无误后,再创建订单,流程结束;
5、图片中齿轮图标表示无须人工处理的服务任务,人形图标为须人工处理的用户任务;
6、x表示排他网关,细线的圆圈表示开始节点,粗线的圆圈表示结束节点。
下面使用springboot整合flowable实现上面的工作流处理。
项目总体结构预览:

**准备工作:**在flowable-ui网页端生成模型文件然后导出,文末会告知如何使用flowable-ui创建模型
1、创建springboot工程
在maven中引入必要的依赖
核心依赖是:flowable-spring-boot-starter
XML
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</dependency>
</dependencies>
2、配置flowable和数据库信息
将flowable相关数据存到Mysql,事先到mysql中创建一个flowable的空数据库。
XML
flowable:
# 是否激活异步执行器
async-executor-activate: false
# 数据库模式更新策略,true表示自动更新数据库模式
database-schema-update: true
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.56.10:3309/flowable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
3、拷贝模型文件到项目中
然后在Springboot工程中resources文件夹中创建processes文件夹,将模型xml文件复制到processes文件夹,文末会告知如何导出模型xml文件。
4、启动项目
当项目成功启动后,flowable会向指定数据库生成所需的表,无需手动创建,控制台打印部分信息如下:
performing create on history with resource org/flowable/db/create/flowable.mysql.create.history.sql
performing create on engine with resource org/flowable/db/create/flowable.mysql.create.engine.sql
此时再刷新数据库,会发现多出很多表。
5、创建订单实体类
java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {
private String customer;
private Integer total;
}
6、创建订单处理器和邮件抄送执行器
java
package com.example.flowabledemo.process;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
@Slf4j
public class CreateOrderProcessor implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
log.info("订单创建成功,{}",execution.getVariable("order"));
}
}
这段代码是 Flowable 工作流框架中的「服务任务(Service Task)」执行器,实现了 Flowable 提供的 JavaDelegate 接口,核心作用是:当流程执行到绑定该类的「创建订单」服务任务节点时,自动触发 execute 方法,打印订单创建成功的日志,并从流程上下文获取 order 变量。
java
package com.example.flowabledemo.process;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
@Slf4j
public class SendEmailProcessor implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
log.info("发送审批邮件,{}",execution.getVariable("order"));
}
}
7、订单处理相关接口
7.1 创建订单
java
@Controller
@RequestMapping("order")
@Slf4j
public class OrderFlowController {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private ProcessEngine processEngine;
/* *
* 创建订单
**/
@PostMapping("createOrder")
public ResponseEntity<String> startFlow(String customer,Integer total){
HashMap<String,Object>map=new HashMap<>();
map.put("order",new Order(customer,total));
map.put("initiator", customer);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("order-approval-process", map);
String processId = processInstance.getId();
log.info("{}流程实例ID:{}",processInstance.getProcessDefinitionName(),processId);
Task task = taskService.createTaskQuery().processInstanceId(processId).active().singleResult();
taskService.complete(task.getId());
return ResponseEntity.ok(processId);
}
代码解读:
- 核心作用:接收客户名称和订单金额参数,启动「订单审批流程(order-approval-process)」,并自动完成流程中第一个待办任务(「填写订单」节点),最终返回流程实例 ID,。
- 初始化
HashMap存储流程变量(Flowable 流程实例的全局变量,贯穿整个流程生命周期),map.put("order", new Order(...):将订单对象存入流程变量,供后续节点(如创建订单、经理审批)获取;runtimeService.startProcessInstanceByKey(...):Flowable 核心方法,通过「流程定义 Key」启动流程实例,order-approval-process:BPMN 文件中<process id="order-approval-process">的 ID,是流程的唯一标识,必须保持一致;taskService.createTaskQuery():创建任务查询器,筛选「当前流程实例的活跃任务」;
processInstanceId(processId):仅查询该流程实例的任务;active():仅查询未完成的活跃任务;singleResult():返回单个任务(预期流程第一个节点是「填写订单」用户任务,仅一个活跃任务);taskService.complete(task.getId()):完成该任务,流程会自动流转到下一个节点(排他网关,判断金额分支)。
7.2 查询经理要审批的订单列表
java
@GetMapping("list")
public String getOrderList(){
List<Task> taskList = taskService.createTaskQuery().taskAssignee("manager").list();
StringBuilder sb = new StringBuilder();
for(Task task:taskList){
Object obj = runtimeService.getVariable(task.getExecutionId(), "order");
if(obj instanceof Order){
sb.append(task.getId()+ ":" + (Order) obj);
}
}
return sb.toString();
}
代码解读:
- 核心作用是:查询并返回分配给「manager」(经理)的所有待审批订单任务列表,具体逻辑是先获取经理的待办任务,再从每个任务对应的流程实例中提取
order变量(订单对象),最终拼接任务 ID 和订单信息返回字符串。taskService:Flowable 核心服务类,用于操作「用户任务」(待办、已办、完成任务等);createTaskQuery():创建任务查询器,Flowable 采用「查询器模式」封装数据库查询逻辑;taskAssignee("manager"):筛选条件 ------ 仅查询分配给「manager」(经理)的任务(对应 BPMN 中flowable:assignee="manager"的节点);list():执行查询,返回符合条件的所有任务列表(区别于singleResult()返回单个任务);task.getExecutionId():获取任务所属的「流程执行 ID」(对应单个流程实例的执行分支 ID,可关联到流程实例);runtimeService.getVariable(...):Flowable 核心服务类,用于操作流程实例的「流程变量」,这里根据执行 ID 获取名为order的变量;obj instanceof Order:类型校验,避免强制类型转换时抛出ClassCastException;sb.append(...):拼接「任务 ID: 订单对象」,最终返回拼接后的字符串。
7.3 经理确认和审批订单
java
@PostMapping("/confirm/{taskId}")
public ResponseEntity<String> confirmOrder(@PathVariable String taskId){
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("verified",true);
taskService.complete(taskId,map);
return ResponseEntity.ok("success");
}
代码解读:
- 核心作用是:接收「任务 ID(taskId)」路径参数,完成该任务(对应经理审批订单的节点),并通过流程变量
verified标记「审批通过」,最终返回成功提示,触发流程向下一个节点(创建订单)流转。- 构造
HashMap存储「任务完成时的流程变量」:verified=true标记订单「审批通过」(若有驳回场景,可传false);taskService.complete(taskId, map):Flowable 核心方法,完成指定 ID 的任务,并将变量传入流程上下文:
8、注意事项:
8.1、邮件抄送的类,必须与代码中声明的保持一致,使用全限定名,邮件抄送是一样的处理逻辑,可打开工作流程图,点击任务节点,在下方的节点详细信息中进行编辑,记得要保存,参照下图:

8.2、经理确认,必须指定分配级哪个用户进行处理,这里必须与接口list中
taskAssignee("manager")保持一致

8.3、排他网关,当订单金额超过10万时,走上面的分支进行处理,须指定工作流条件和是否默认流

这里的流条件order.total与代码中声明的流变量保持对应关系,包括map中的key,total为order对象中一个属性。
map.put("order",new Order(customer,total));
金额不超过10时的工作流,这个不用设置条件,执行默认流处理:

8.4、执行了修改,一定要点击左上角的第1个保存按钮才会生效,第2个按钮对勾为检查语法有无错误:

8.5、模块的Key必须与接口中createOrder中这一行代码中保持一致:
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("order-approval-process", map);

8.6、flowable-ui模型导入
flowable-ui网页端可以对模型执行导入操作,导入的模型名称必须是**.bpmn.xml或.bpmn20.xml**,注意以点号开头,如果文件命名为其他,导入的时候会提示文件名错误,无法解析。


8.7、flowable-ui模型导出
在flowable-ui模型列表中点击要导出的模型,在弹出的模型详情页面中点击右上角的下载图标,即可将模型导出为xml文件,点击后自动生成文件名,使用默认的文件名即可

8.8、创建模型
输入模型名称和模型的key
8.8.1 模型名称
输入的模型名称是什么,导出时模型文件名称自动在模型名称后面添加后缀,如这里我命名为OrderFlow,导出的文件名则为OrderFlow.bpmn20.xml
8.8.2 模型key
这里输入的key是什么,那么在启动流程时变量命名必须与它保持一致,我这里命名为order,所以在启动流程时就命名为order,否则会报错




9、接口请求示例


