3、Flowable 核心概念与 Spring Boot 3 集成组件详解

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.6k人参与

一、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 工作流引擎,实现灵活、可靠的业务流程自动化。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值