Flowable-企业级可视化工作流引擎实现
·
SpringBoot + Flowable + 自定义节点:企业级可视化工作流引擎实现
一、传统工作流痛点与解决方案
1.1 传统硬编码流程的问题
- 开发效率低:每个流程(请假、报销、采购等)需独立开发状态机逻辑,代码重复率高
- 维护成本高:流程变更需重新开发部署,响应业务变化慢
- 灵活性差:业务人员无法自主配置流程,依赖技术团队
1.2 解决方案:可视化工作流引擎
基于 SpringBoot + Flowable + 自定义节点,实现:
- 可视化流程定义:通过BPMN 2.0标准定义流程,支持拖拽设计
- 灵活扩展:自定义业务节点适配复杂场景(如动态审批人、条件分支)
- 低代码配置:业务人员可通过界面调整流程,无需代码开发
二、技术选型与架构设计
2.1 核心技术栈
- Flowable:基于BPMN 2.0的企业级工作流引擎,支持流程定义、实例管理、任务调度
- SpringBoot:快速集成Flowable,提供自动配置、AOP、事件监听等能力
- 自定义节点:通过JavaDelegate、ExpressionCondition等扩展业务逻辑
2.2 系统架构模块
| 模块 | 功能描述 |
|---|---|
| 流程定义管理 | BPMN流程的部署、查询、版本控制 |
| 流程实例管理 | 流程启动、暂停、终止,支持流程变量传递 |
| 任务管理 | 待办任务查询、审批、分配,支持任务状态跟踪 |
| 自定义节点 | 扩展业务逻辑(如动态审批人、数据校验、通知发送) |
| 流程监控 | 流程执行状态、耗时统计、异常报警 |
| 权限控制 | 任务访问权限校验,确保数据安全性 |
三、核心实现:从基础配置到流程运行
3.1 Flowable基础配置
配置流程引擎,连接数据库并启用必要组件:
@Configuration
@EnableProcessApplication
public class FlowableConfig {
@Bean
public ProcessEngineConfiguration processEngineConfiguration() {
ProcessEngineConfiguration config = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration();
// 数据库配置(MySQL示例)
config.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?useUnicode=true&characterEncoding=utf8");
config.setJdbcUsername("root");
config.setJdbcPassword("password");
config.setJdbcDriver("com.mysql.cj.jdbc.Driver");
// 自动创建表(生产环境建议手动执行脚本)
config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 启用异步执行器(处理定时任务、异步节点)
config.setAsyncExecutorActivate(true);
return config;
}
@Bean
public ProcessEngine processEngine() {
return processEngineConfiguration().buildProcessEngine();
}
}
3.2 流程定义与实例管理
流程部署与启动
通过RepositoryService部署BPMN流程定义,RuntimeService启动流程实例:
@Service
public class ProcessDefinitionService {
@Autowired private RepositoryService repositoryService;
@Autowired private RuntimeService runtimeService;
// 部署BPMN流程(支持XML字符串或文件)
public String deployProcess(String processName, String bpmnXml) {
Deployment deployment = repositoryService.createDeployment()
.name(processName)
.addString(processName + ".bpmn", bpmnXml) // BPMN XML定义
.deploy();
return deployment.getId(); // 返回部署ID
}
// 启动流程实例(传递业务参数)
public String startProcess(String processDefinitionKey, Map<String, Object> variables) {
ProcessInstance instance = runtimeService.startProcessInstanceByKey(
processDefinitionKey, variables); // processDefinitionKey对应BPMN中的process id
return instance.getId(); // 返回流程实例ID
}
}
3.3 任务管理:待办与审批
通过TaskService处理任务分配、完成,支持查询用户待办:
@Service
public class TaskService {
@Autowired private org.flowable.task.api.TaskService taskService;
// 获取用户待办任务
public List<TaskDto> getTodoTasks(String assignee) {
return taskService.createTaskQuery()
.taskAssignee(assignee) // 按处理人查询
.orderByTaskCreateTime().desc()
.list().stream()
.map(this::convertToDto) // 转换为DTO
.collect(Collectors.toList());
}
// 完成任务(传递审批结果等变量)
public void completeTask(String taskId, Map<String, Object> variables) {
taskService.complete(taskId, variables); // variables包含审批结果(如approved: true)
}
// 任务分配(支持动态调整处理人)
public void assignTask(String taskId, String assignee) {
taskService.setAssignee(taskId, assignee);
}
}
四、自定义节点:业务逻辑扩展核心
4.1 自定义业务逻辑节点(JavaDelegate)
实现JavaDelegate接口,在流程中嵌入自定义业务逻辑(如通知发送、数据校验):
@Component
public class NotificationNode implements JavaDelegate {
@Autowired private EmailService emailService;
@Override
public void execute(DelegateExecution execution) {
// 从流程变量获取参数
String employeeId = (String) execution.getVariable("employeeId");
String processInstanceId = execution.getProcessInstanceId();
// 执行业务逻辑(发送审批通知)
emailService.send(
employeeId,
"流程通知",
"您的流程" + processInstanceId + "已到达审批节点"
);
// 记录执行日志
execution.setVariable("notificationTime", new Date());
}
}
BPMN中引用节点:在serviceTask中配置flowable:class指向该类:
<serviceTask id="notificationTask" name="发送通知"
flowable:class="com.example.node.NotificationNode"/>
4.2 动态任务分配节点
根据业务规则动态确定审批人(如“直属领导→部门领导→总经理”):
@Component
public class DynamicApproverNode implements JavaDelegate {
@Autowired private UserService userService;
@Override
public void execute(DelegateExecution execution) {
String employeeId = (String) execution.getVariable("employeeId");
Integer leaveDays = (Integer) execution.getVariable("leaveDays");
// 根据请假天数动态确定审批人
String approverId;
if (leaveDays > 7) {
approverId = userService.getManagerByLevel(employeeId, "general"); // 总经理
} else if (leaveDays > 3) {
approverId = userService.getManagerByLevel(employeeId, "department"); // 部门领导
} else {
approverId = userService.getManagerByLevel(employeeId, "direct"); // 直属领导
}
// 设置下一个任务的处理人(通过流程变量传递给 userTask)
execution.setVariable("approverId", approverId);
}
}
BPMN中使用动态分配:在userTask中通过表达式引用变量:
<userTask id="approveTask" name="审批" flowable:assignee="${approverId}"/>
4.3 条件分支节点(ExpressionCondition)
根据流程变量动态决定流程走向(如金额阈值判断):
@Component
public class ExpenseConditionNode implements ExpressionCondition {
@Override
public boolean evaluate(DelegateExecution execution) {
// 报销金额 > 5000 需CEO审批
Double amount = (Double) execution.getVariable("expenseAmount");
return amount > 5000;
}
}
BPMN中配置分支条件:
<exclusiveGateway id="amountGateway" name="金额判断"/>
<sequenceFlow id="toCeo" sourceRef="amountGateway" targetRef="ceoApproval">
<conditionExpression xsi:type="tFormalExpression">
${expenseAmount > 5000}
</conditionExpression>
</sequenceFlow>
五、典型场景示例:请假与报销流程
5.1 请假流程实现
流程定义(BPMN核心节点)
<process id="leaveProcess" name="请假流程" isExecutable="true">
<startEvent id="start"/>
<!-- 填写请假单 -->
<userTask id="fillLeave" name="填写请假单" flowable:assignee="${employeeId}"/>
<!-- 动态确定审批人 -->
<serviceTask id="determineApprover" flowable:class="com.example.node.DynamicApproverNode"/>
<!-- 审批任务 -->
<userTask id="approveTask" name="审批" flowable:assignee="${approverId}"/>
<!-- 结束 -->
<endEvent id="end"/>
<sequenceFlow sourceRef="start" targetRef="fillLeave"/>
<sequenceFlow sourceRef="fillLeave" targetRef="determineApprover"/>
<sequenceFlow sourceRef="determineApprover" targetRef="approveTask"/>
<sequenceFlow sourceRef="approveTask" targetRef="end"/>
</process>
流程服务层实现
@Service
public class LeaveProcessService {
@Autowired private ProcessDefinitionService processService;
@Autowired private TaskService taskService;
// 提交请假申请
public String submitLeave(LeaveRequest request) {
Map<String, Object> variables = new HashMap<>();
variables.put("employeeId", request.getEmployeeId());
variables.put("leaveDays", request.getLeaveDays());
// 启动流程实例
return processService.startProcess("leaveProcess", variables);
}
// 审批请假
public void approveLeave(String taskId, boolean approved) {
Map<String, Object> variables = new HashMap<>();
variables.put("approved", approved);
taskService.completeTask(taskId, variables);
}
}
5.2 报销流程:金额分支与财务审核
通过排他网关实现金额分级审批:
- ≤1000元:部门领导审批
- 1000~5000元:财务审批
-
5000元:CEO审批
BPMN核心片段:
<exclusiveGateway id="amountCheck"/>
<!-- 部门领导审批(≤1000) -->
<sequenceFlow sourceRef="amountCheck" targetRef="deptApproval">
<conditionExpression>${expenseAmount <= 1000}</conditionExpression>
</sequenceFlow>
<!-- 财务审批(1000~5000) -->
<sequenceFlow sourceRef="amountCheck" targetRef="financeApproval">
<conditionExpression>${expenseAmount > 1000 && expenseAmount <= 5000}</conditionExpression>
</sequenceFlow>
<!-- CEO审批(>5000) -->
<sequenceFlow sourceRef="amountCheck" targetRef="ceoApproval">
<conditionExpression>${expenseAmount > 5000}</conditionExpression>
</sequenceFlow>
六、高级特性:监听器与流程监控
6.1 流程监听器(ExecutionListener)
监控流程生命周期事件(启动、结束、节点流转):
@Component
public class ProcessListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
String eventName = execution.getEventName();
if ("start".equals(eventName)) {
// 流程启动时记录日志
log.info("流程启动: {}", execution.getProcessInstanceId());
} else if ("end".equals(eventName)) {
// 流程结束时更新业务状态
String businessKey = execution.getVariable("businessKey");
businessService.updateStatus(businessKey, "completed");
}
}
}
6.2 任务监听器(TaskListener)
处理任务创建、分配、完成事件(如发送待办通知):
@Component
public class TaskCreateListener implements org.flowable.task.api.TaskListener {
@Autowired private NotificationService notificationService;
@Override
public void notify(DelegateTask task) {
if ("create".equals(task.getEventName())) {
// 任务创建时发送通知给处理人
notificationService.sendTodo(task.getAssignee(), task.getName());
}
}
}
6.3 流程监控与指标
通过HistoryService查询流程历史,结合Prometheus监控关键指标:
@Service
public class ProcessMonitorService {
@Autowired private HistoryService historyService;
// 查询流程执行时长
public long getProcessDuration(String processInstanceId) {
HistoricProcessInstance instance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
return instance.getDurationInMillis();
}
// 记录流程启动指标(配合Prometheus)
public void recordProcessStart(String processKey) {
MeterRegistry counter = ...; // 注入MeterRegistry
counter.counter("process.start", "processKey", processKey).increment();
}
}
七、生产级优化与最佳实践
7.1 性能优化
- 流程实例缓存:通过Redis缓存高频访问的流程实例(如待办任务)
- 批量任务处理:使用CompletableFuture异步批量完成任务,提升吞吐量
- 数据库优化:合理配置连接池,索引流程实例ID、任务处理人等字段
7.2 安全措施
- 权限控制:校验用户是否为任务合法处理人(
TaskPermissionService) - 数据脱敏:流程变量中敏感信息(如银行卡号)脱敏存储
- 防重放攻击:通过nonce机制防止任务重复提交
7.3 流程设计规范
- 单一职责:一个流程专注一个业务场景(如请假流程、报销流程分离)
- 异常处理:通过
BPMNError定义业务异常,支持流程回退或终止 - 版本控制:流程定义支持版本管理,避免新旧流程冲突
八、总结
通过 SpringBoot + Flowable + 自定义节点,可构建灵活、可扩展的企业级工作流引擎,核心优势:
- 标准化:基于BPMN 2.0,支持可视化设计与版本管理
- 低代码:业务人员通过界面配置流程,减少开发依赖
- 高扩展:自定义节点适配复杂业务逻辑,如动态审批、条件分支
- 易维护:流程与业务逻辑解耦,变更无需代码重构
适用于企业OA、审批系统、供应链管理等场景,助力业务流程数字化与自动化。
更多推荐





所有评论(0)