一、Flowable 核心概念及其作用
1. 流程定义(Process Definition)
- 定义:BPMN 2.0 流程模型的静态描述,存储在数据库中(
ACT_RE_PROCDEF表) - 作用:描述流程的结构(节点、连线、规则),是流程实例的“蓝图”
- 特点:
- 每次部署 BPMN 文件会生成一个新的流程定义(版本号递增)
- Key(流程定义ID)必须唯一,用于启动流程
2. 流程实例(Process Instance)
- 定义:流程定义的一次具体执行,存储在运行时表(
ACT_RU_EXECUTION) - 作用:代表一个实际业务流程的运行状态(如“张三的请假申请”)
- 特点:
- 一个流程定义可对应多个流程实例
- 实例结束(到达结束事件)后,数据移至历史表(
ACT_HI_PROCINST)
3. 任务(Task)
- 定义:流程中需要人工处理的工作单元,分为:
UserTask:用户任务(需人办理)ServiceTask:服务任务(自动执行 Java 逻辑)
- 作用:驱动流程前进,协调人与系统的交互
- 特点:
- 用户任务存储在
ACT_RU_TASK(运行时)和ACT_HI_TASKINST(历史)
- 用户任务存储在
4. 执行流(Execution)
- 定义:流程实例中当前活跃的执行路径
- 作用:在并行网关、子流程等场景中,一个流程实例可能有多个 Execution
- 特点:
- 每个 Execution 代表一条执行分支
- 任务(Task)是 Execution 的一种特殊形式
5. 流程变量(Process Variables)
- 定义:与流程实例关联的键值对数据
- 作用:
- 在流程节点间传递业务数据(如
days=3,approved=true) - 用于条件表达式(如
${days > 5})
- 在流程节点间传递业务数据(如
- 特点:
- 支持基本类型、Serializable 对象、JSON
- 存储在
ACT_RU_VARIABLE(运行时)和ACT_HI_VARINST(历史)
6. 历史数据(History)
- 定义:已完成的流程实例、任务、变量的审计记录
- 作用:提供流程追溯、性能分析、合规审计能力
- 特点:
- 历史级别可配置(
none,activity,audit,full) - 默认级别为
audit(记录关键节点)
- 历史级别可配置(
二、Spring Boot 3 集成 Flowable 的核心组件
| 组件 | 类型 | 作用 | 获取方式 |
|---|---|---|---|
| RepositoryService | 服务类 | 管理流程定义:部署、查询、删除 | @Autowired |
| RuntimeService | 服务类 | 管理流程实例:启动、查询、信号 | @Autowired |
| TaskService | 服务类 | 管理用户任务:查询、办理、委托 | @Autowired |
| HistoryService | 服务类 | 查询历史数据:已完成的流程/任务 | @Autowired |
| IdentityService | 服务类 | 管理用户与组(IDM) | @Autowired |
| ManagementService | 服务类 | 管理作业(Job):定时任务、异步任务 | @Autowired |
| FormService | 服务类 | 处理表单数据(已废弃,推荐用变量) | @Autowired |
💡 记忆口诀:
“仓运任历身管表” → Repository, Runtime, Task, History, Identity, Management, Form
三、核心组件使用示例(含详细中文注释)
环境准备
- Spring Boot 3.2+
- Flowable 6.8.2+
- 数据库:PostgreSQL / MySQL
示例 1:RepositoryService —— 流程定义管理
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;
/**
* 流程定义管理服务
* 负责 BPMN 文件的部署、查询、删除等操作
*/
@Service
public class ProcessDefinitionService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private ResourcePatternResolver resourceResolver;
/**
* 从 classpath 部署单个 BPMN 文件
*
* @param bpmnFileName BPMN 文件名(如 "leave-process.bpmn20.xml")
* @param processName 流程名称(显示用)
* @return 部署ID
*/
public String deployBpmnFile(String bpmnFileName, String processName) {
// 从 resources 目录加载 BPMN 文件
Resource resource = resourceResolver.getResource("classpath:processes/" + bpmnFileName);
try (InputStream inputStream = resource.getInputStream()) {
// 创建部署构建器
Deployment deployment = repositoryService.createDeployment()
.name(processName) // 部署名称
.addInputStream(bpmnFileName, inputStream) // 添加 BPMN 文件流
.deploy(); // 执行部署
return deployment.getId();
} catch (Exception e) {
throw new RuntimeException("部署 BPMN 文件失败: " + bpmnFileName, e);
}
}
/**
* 从 ZIP 包部署多个流程文件(BPMN + PNG)
*
* @param zipResource ZIP 资源路径
* @return 部署ID
*/
public String deployBpmnZip(String zipResource) {
Resource resource = resourceResolver.getResource("classpath:" + zipResource);
try (InputStream inputStream = resource.getInputStream()) {
Deployment deployment = repositoryService.createDeployment()
.name("批量流程部署")
.addZipInputStream(new ZipInputStream(inputStream))
.deploy();
return deployment.getId();
} catch (Exception e) {
throw new RuntimeException("部署 ZIP 失败", e);
}
}
/**
* 查询所有流程定义(按版本倒序)
*
* @return 流程定义列表
*/
public List<ProcessDefinition> getAllProcessDefinitions() {
return repositoryService.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion().desc() // 按版本号倒序
.list();
}
/**
* 根据流程定义Key查询最新版本
*
* @param processDefinitionKey 流程定义ID(BPMN 中的 process id)
* @return 最新版本的流程定义
*/
public ProcessDefinition getLatestProcessDefinition(String processDefinitionKey) {
return repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)
.latestVersion() // 只查最新版本
.singleResult();
}
/**
* 删除流程定义(级联删除实例)
*
* @param deploymentId 部署ID
*/
public void deleteDeployment(String deploymentId) {
// true 表示级联删除:同时删除关联的流程实例、历史数据等
repositoryService.deleteDeployment(deploymentId, true);
}
}
示例 2:RuntimeService —— 流程实例管理
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 流程实例管理服务
* 负责启动、查询、操作流程实例
*/
@Service
public class ProcessInstanceService {
@Autowired
private RuntimeService runtimeService;
/**
* 启动流程实例(最常用方法)
*
* @param processDefinitionKey 流程定义Key(BPMN 中的 process id)
* @param businessKey 业务主键(如订单ID、请假单ID)
* @param variables 流程变量(用于初始化任务分配、条件判断等)
* @return 流程实例对象
*/
public ProcessInstance startProcessInstance(
String processDefinitionKey,
String businessKey,
Map<String, Object> variables) {
return runtimeService.startProcessInstanceByKey(
processDefinitionKey, // 流程定义ID
businessKey, // 业务主键(可用于关联业务系统)
variables // 流程变量
);
}
/**
* 启动流程实例(简化版,无业务主键)
*/
public ProcessInstance startProcessInstance(String processDefinitionKey, Map<String, Object> variables) {
return runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
}
/**
* 查询正在运行的流程实例
*
* @param processDefinitionKey 流程定义Key
* @param variables 查询条件(流程变量)
* @return 流程实例列表
*/
public List<ProcessInstance> getRunningProcessInstances(
String processDefinitionKey,
Map<String, Object> variables) {
return runtimeService.createProcessInstanceQuery()
.processDefinitionKey(processDefinitionKey)
.processInstanceVariables(variables) // 按变量查询
.active() // 只查活跃实例(未结束)
.list();
}
/**
* 触发信号(用于 Signal Intermediate Event)
*
* @param signalName 信号名称
* @param variables 信号携带的变量
*/
public void sendSignal(String signalName, Map<String, Object> variables) {
runtimeService.signalEventReceived(signalName, variables);
}
/**
* 删除流程实例(谨慎使用!)
*
* @param processInstanceId 流程实例ID
* @param deleteReason 删除原因(记录到历史表)
*/
public void deleteProcessInstance(String processInstanceId, String deleteReason) {
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
}
}
示例 3:TaskService —— 用户任务管理
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.engine.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用户任务管理服务
* 负责查询、办理、委托任务
*/
@Service
public class TaskServiceExample {
@Autowired
private TaskService taskService;
/**
* 查询用户的待办任务(最常用)
*
* @param assignee 任务办理人(用户名)
* @return 任务列表
*/
public List<Task> getTasksForUser(String assignee) {
return taskService.createTaskQuery()
.taskAssignee(assignee) // 指定办理人
.orderByTaskCreateTime().desc() // 按创建时间倒序
.list();
}
/**
* 查询候选组的任务(组任务)
*
* @param candidateGroup 候选组名(如 "managers")
* @return 任务列表
*/
public List<Task> getTasksForGroup(String candidateGroup) {
return taskService.createTaskQuery()
.taskCandidateGroup(candidateGroup)
.orderByTaskCreateTime().desc()
.list();
}
/**
* 签收组任务(将组任务分配给具体用户)
*
* @param taskId 任务ID
* @param assignee 办理人
*/
public void claimTask(String taskId, String assignee) {
taskService.claim(taskId, assignee);
}
/**
* 完成任务(核心操作!)
*
* @param taskId 任务ID
* @param variables 任务办理时提交的变量(如审批意见)
*/
public void completeTask(String taskId, Map<String, Object> variables) {
// variables 会作为流程变量传递到下一个节点
taskService.complete(taskId, variables);
}
/**
* 完成任务(无变量)
*/
public void completeTask(String taskId) {
taskService.complete(taskId);
}
/**
* 委托任务(将任务临时交给他人办理)
*
* @param taskId 任务ID
* @param delegateTo 被委托人
*/
public void delegateTask(String taskId, String delegateTo) {
taskService.delegateTask(taskId, delegateTo);
}
/**
* 解决委托(委托人收回任务)
*/
public void resolveTask(String taskId) {
taskService.resolveTask(taskId);
}
/**
* 设置任务局部变量(仅当前任务可见,不影响流程变量)
*/
public void setTaskLocalVariable(String taskId, String variableName, Object value) {
taskService.setVariableLocal(taskId, variableName, value);
}
}
示例 4:HistoryService —— 历史数据查询
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricTaskInstance;
import org.flowable.engine.HistoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 历史数据查询服务
* 用于审计、报表、流程分析
*/
@Service
public class HistoryServiceExample {
@Autowired
private HistoryService historyService;
/**
* 查询用户已办理的历史任务
*
* @param assignee 办理人
* @return 历史任务列表
*/
public List<HistoricTaskInstance> getHistoricTasks(String assignee) {
return historyService.createHistoricTaskInstanceQuery()
.taskAssignee(assignee)
.orderByHistoricTaskInstanceEndTime().desc() // 按结束时间倒序
.list();
}
/**
* 查询已完成的流程实例
*
* @param processDefinitionKey 流程定义Key
* @param businessKey 业务主键
* @return 流程实例
*/
public HistoricProcessInstance getCompletedProcessInstance(
String processDefinitionKey,
String businessKey) {
return historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey(processDefinitionKey)
.processInstanceBusinessKey(businessKey)
.finished() // 只查已完成的
.singleResult();
}
/**
* 查询流程实例的完整历史轨迹(用于流程图高亮)
*
* @param processInstanceId 流程实例ID
* @return 所有历史活动实例
*/
public List<org.flowable.engine.history.HistoricActivityInstance> getProcessHistory(String processInstanceId) {
return historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime().asc()
.list();
}
/**
* 查询历史流程变量
*
* @param processInstanceId 流程实例ID
* @return 变量列表
*/
public List<org.flowable.engine.history.HistoricVariableInstance> getHistoricVariables(String processInstanceId) {
return historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstanceId)
.list();
}
}
示例 5:IdentityService —— 用户与组管理
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.idm.api.IdmIdentityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 用户与组管理服务
* 管理 Flowable 内置的用户体系(ACT_ID_* 表)
*/
@Service
public class IdentityServiceExample {
// 注意:在 Spring Boot 中,IdentityService 的 Bean 名为 idmIdentityService
@Autowired
private IdmIdentityService identityService;
/**
* 创建用户
*
* @param userId 用户ID
* @param firstName 名
* @param lastName 姓
* @param email 邮箱
* @param password 密码(Flowable UI 会使用)
*/
public void createUser(String userId, String firstName, String lastName, String email, String password) {
User user = identityService.newUser(userId);
user.setFirstName(firstName);
user.setLastName(lastName);
user.setEmail(email);
// 注意:Flowable 默认不加密密码,生产环境需自行处理
user.setPassword(password);
identityService.saveUser(user);
}
/**
* 创建用户组
*
* @param groupId 组ID
* @param groupName 组名
*/
public void createGroup(String groupId, String groupName) {
Group group = identityService.newGroup(groupId);
group.setName(groupName);
group.setType("assignment"); // 类型:assignment(任务分配), security(安全组)
identityService.saveGroup(group);
}
/**
* 将用户加入组
*
* @param userId 用户ID
* @param groupId 组ID
*/
public void addUserToGroup(String userId, String groupId) {
identityService.createMembership(userId, groupId);
}
/**
* 验证用户密码(用于自定义登录)
*/
public boolean checkPassword(String userId, String password) {
return identityService.checkPassword(userId, password);
}
}
示例 6:ManagementService —— 作业管理(定时/异步任务)
import org.flowable.job.api.Job;
import org.flowable.engine.ManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 作业管理服务
* 管理定时任务、异步任务、消息重试等
*/
@Service
public class ManagementServiceExample {
@Autowired
private ManagementService managementService;
/**
* 查询所有待执行的作业(Job)
*
* @return 作业列表
*/
public List<Job> getPendingJobs() {
return managementService.createJobQuery().list();
}
/**
* 手动执行一个作业(用于调试或补偿)
*
* @param jobId 作业ID
*/
public void executeJob(String jobId) {
managementService.executeJob(jobId);
}
/**
* 删除作业(谨慎!可能导致流程卡住)
*/
public void deleteJob(String jobId) {
managementService.deleteJob(jobId);
}
/**
* 获取数据库表元数据(用于监控)
*/
public List<String> getTableNames() {
return managementService.getTableNames();
}
/**
* 获取表数据量(用于容量规划)
*/
public long getTableCount(String tableName) {
return managementService.getTableCount(tableName);
}
}
四、关键注意事项
1. 事务管理
- 所有 Flowable 操作必须在 Spring 事务中执行
- 使用
@Transactional注解确保数据一致性
@Service
public class WorkflowService {
@Transactional // 关键!
public void startAndCompleteProcess() {
// 启动流程 + 完成任务 应在同一个事务中
}
}
2. 历史级别配置
# application.yml
flowable:
history-level: full # full 记录所有变量,audit 只记录关键节点
3. 异步执行器
- 复杂逻辑建议开启异步执行器,避免阻塞 HTTP 线程
flowable:
async-executor-activate: true
4. 性能优化
- 查询任务时务必加索引(如
taskAssignee,processDefinitionKey) - 避免在循环中调用 Flowable API(批量操作更高效)
五、总结
| 组件 | 核心用途 | 典型场景 |
|---|---|---|
| RepositoryService | 流程定义生命周期 | 部署 BPMN、查询流程 |
| RuntimeService | 流程实例控制 | 启动流程、发送信号 |
| TaskService | 任务操作 | 办理任务、签收组任务 |
| HistoryService | 历史审计 | 查询已办任务、流程轨迹 |
| IdentityService | 用户管理 | 创建用户/组、权限分配 |
| ManagementService | 系统运维 | 定时任务、监控表数据 |
💡 最佳实践:
- 将 Flowable 操作封装在
@Service中,并添加@Transactional- 通过流程变量传递业务数据,避免硬编码
- 利用历史服务实现流程追溯与分析
通过以上组件,你可以在 Spring Boot 3 应用中完全掌控 Flowable 工作流引擎,实现灵活、可靠的业务流程自动化。
3223

被折叠的 条评论
为什么被折叠?



