xml
// 兼容 java 8
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.8.1</version>
</dependency>
// 兼容 java 17
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>7.2.0</version>
</dependency>📚 BPMN
📖 任务类型
<userTask>用户任务<serviceTask>服务任务(自动执行)<scriptTask>脚本任务,执行一段内嵌脚本(Groovy、JavaScript 等)<receiveTask>接收任务,等待外部系统通过 API 回调触发继续执行流程<manualTask>手工任务(引擎只记录,不会分配或等待完成,用于说明性任务)<businessRuleTask>业务规则任务(调用规则引擎(如 Drools)进行判断决策)<callActivity>调用子流程<sendTask>发送任务(向外发送消息)<mailTask>邮件任务<httpTask>HTTP 调用任务
📚 基本概念
- 在 flowable 中生成的实例流程 ID 是全局唯一的(包括所有的父子流程)
📚 常用类
📖 RepositoryService
仓库服务(管理所有流程图文件(.bpmn)的部署与版本)
📖 RuntimeService
运行时服务(负责启动、查询、控制流程实例的运行)
Object getVariable(实例id, variableName)拿到某个实例指定的上下文setVariable(实例id, key, value)直接更新流程变量- 查询流程实例(只能查询正在运行中的流程实例)
java
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceBusinessKey(applicationId)
.singleResult();📖 TaskService
任务服务(审批、签收、查询待办任务)
🏷️ 查询(只能查询正在进行中的 task)
- 查询条件
- 查询结果
list()singleResult()存在多个报错
java
taskService.createTaskQuery()
.processInstanceBusinessKey(businessKey)
.active() // 活动的任务
.taskAssignee(userId) // 指定办理人
.taskCandidateUser(userId) // 候选人
.orderByTaskCreateTime().desc() // 按创建时间排序
.singleResult();java
// 查询当前任务
Task currentTask = taskService.createTaskQuery()
.processInstanceBusinessKey(businessKey) // 通过业务key查询
.active() // 只查询活动的任务
.singleResult(); // 获取单个结果📚 监听器
📖 FlowableEventListener
记录流程日志、审计、监控、业务状态同步
📖 ExecutionListener
🏷️ 适用于所有流程元素
🏷️ 事件类型
- start 节点开始
- end 节点结束
- take 连线流转
📖 TaskListener
🏷️ 只适用于 UserTask 任务。任务自动指派、任务属性修改、消息通知
🏷️ TaskListener 和 Flowable 流程推进默认是在同一个线程同一个事务中,是强关联的(如果 TaskListener 中抛出异常,Flowable 的流程推进会回滚,整个操作失败)
🏷️ 事件类型
- create 任务创建
- assignment 任务被指派
- complete 任务完成
📚 其他
📖 JavaDelegate
如果 JavaDelegate 抛出异常:
- 当前事务会回滚
- 节点不会被标记完成
- 流程不会推进到下一个节点
📚 动态创建流程
📖 Call Activity
- 当 Call Activity 的所有实例都走完后,后续就不能再动态创建实例了
📖 事件子流程
📚 例子
- 一旦 overallInvoiceStatus == 'FULLY_INVOICED' 并且父流程通过条件事件结束了发票容器:
- 已经存在的事件子流程可以继续完成,不会中断
- 新的发票事件子流程无法再创建
xml
<!-- ==================== 分支1:发票处理容器(包含事件子流程) ==================== -->
<subProcess id="invoiceProcessContainer" name="发票处理流程容器">
<!-- 容器内主流程:等待发票完成 -->
<startEvent id="invoiceContainerStart" name="发票流程开始"/>
<!-- 等待发票全部完成的中间事件 -->
<intermediateCatchEvent id="waitInvoiceComplete" name="等待发票完成">
<conditionalEventDefinition>
<condition xsi:type="tFormalExpression">
${overallInvoiceStatus == 'FULLY_INVOICED'}
</condition>
</conditionalEventDefinition>
</intermediateCatchEvent>
<sequenceFlow id="invoiceContainerFlow1" sourceRef="invoiceContainerStart" targetRef="waitInvoiceComplete"/>
<endEvent id="invoiceContainerEnd" name="发票流程结束"/>
<sequenceFlow id="invoiceContainerFlow2" sourceRef="waitInvoiceComplete" targetRef="invoiceContainerEnd"/>
<!-- ==================== 事件子流程:动态处理每个发票 ==================== -->
<subProcess id="invoiceEventSubProcess" name="发票处理事件子流程" triggeredByEvent="true">
<!-- 消息启动事件(非中断) -->
<startEvent id="invoiceMessageStart" name="收到上传发票请求" isInterrupting="false">
<messageEventDefinition messageRef="uploadInvoiceMessage"/>
</startEvent>
<!-- 上传发票任务 -->
<userTask id="uploadInvoice" name="上传发票" flowable:assignee="${invoiceUser}">
<extensionElements>
<flowable:taskListener event="create" class="com.example.listener.InvoiceUploadListener"/>
</extensionElements>
</userTask>
<sequenceFlow id="eventInvFlow1" sourceRef="invoiceMessageStart" targetRef="uploadInvoice"/>
<!-- 确认发票任务 -->
<userTask id="confirmInvoice" name="确认发票" flowable:assignee="${invoiceManager}">
<extensionElements>
<flowable:taskListener event="complete" class="com.example.listener.InvoiceConfirmListener"/>
</extensionElements>
</userTask>
<sequenceFlow id="eventInvFlow2" sourceRef="uploadInvoice" targetRef="confirmInvoice"/>
<!-- 结束事件 -->
<endEvent id="invoiceEventEnd" name="单个发票处理完成"/>
<sequenceFlow id="eventInvFlow3" sourceRef="confirmInvoice" targetRef="invoiceEventEnd"/>
</subProcess>
</subProcess>