RuoYi-Vue-fast集成Flowable:工作流引擎应用教程
在企业级应用开发中,工作流(Workflow)是实现业务流程自动化的核心组件。本文将详细介绍如何在RuoYi-Vue-fast框架中集成Flowable工作流引擎,帮助开发者快速构建审批、任务流转等业务场景。通过本文,你将掌握环境配置、流程定义、任务管理等关键技能,并能基于实际业务需求扩展工作流功能。
技术栈与环境准备
核心技术栈说明
RuoYi-Vue-fast基于SpringBoot 2.5.15构建,采用前后端分离架构。集成Flowable需引入以下组件:
- Flowable:6.7.2版本(兼容SpringBoot 2.x),提供BPMN 2.0流程引擎
- 数据库:MySQL 8.0+(支持Flowable的历史数据存储)
- 依赖管理:Maven 3.6+(通过pom.xml统一管理版本)
环境依赖配置
首先需要在项目pom.xml中添加Flowable核心依赖。打开pom.xml文件,在<dependencies>节点下添加:
<!-- Flowable工作流核心依赖 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.2</version>
</dependency>
<!-- Flowable REST API支持 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-rest</artifactId>
<version>6.7.2</version>
</dependency>
版本兼容性说明:Flowable 6.7.x系列与SpringBoot 2.5.x保持兼容,更高版本可能需要调整Spring生态组件版本。具体版本对应关系可参考Flowable官方文档。
数据库配置与初始化
数据源配置
Flowable需要独立的数据库表结构存储流程定义、任务实例等数据。修改application.yml(通常位于src/main/resources目录),添加Flowable专用数据源配置:
spring:
datasource:
flowable:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ruoyi_flowable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: password
初始化脚本执行
Flowable提供自动建表功能,启动项目时会自动创建所需表结构。若需手动执行SQL脚本,可从Flowable官网下载对应版本的flowable-all.sql,或通过Maven依赖中的flowable-db.zip获取。
数据库表说明:Flowable会创建23张表,主要分为以下几类:
- ACT_RE_*:流程定义相关(如ACT_RE_PROCDEF流程定义表)
- ACT_RU_*:运行时数据(如ACT_RU_TASK任务实例表)
- ACT_HI_*:历史数据(如ACT_HI_ACTINST活动历史表)
- ACT_GE_*:通用数据(如ACT_GE_BYTEARRAY二进制存储表)
流程引擎配置
核心配置类实现
创建Flowable配置类,位于src/main/java/com/ruoyi/framework/config/FlowableConfig.java,代码如下:
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Autowired
private DataSource flowableDataSource;
@Autowired
private PlatformTransactionManager transactionManager;
@Override
public void configure(SpringProcessEngineConfiguration config) {
config.setDataSource(flowableDataSource);
config.setTransactionManager(transactionManager);
// 禁用Flowable自动部署(建议通过管理界面手动部署)
config.setDeploymentMode("never-fail");
// 配置历史级别为FULL(保存所有流程数据)
config.setHistoryLevel(HistoryLevel.FULL);
// 配置字体支持中文显示
config.setActivityFontName("SimHei");
config.setLabelFontName("SimHei");
config.setAnnotationFontName("SimHei");
}
}
关键配置参数说明
| 参数 | 说明 | 推荐值 |
|---|---|---|
| HistoryLevel | 历史数据保存级别 | FULL(完整记录流程流转) |
| DeploymentMode | 部署模式 | never-fail(部署失败时不中断应用启动) |
| Font配置 | 流程图中文显示支持 | SimHei(宋体) |
| AsyncExecutorActivate | 异步执行器开关 | true(启用异步任务处理) |
流程定义与部署
BPMN文件设计
Flowable使用BPMN 2.0规范定义流程,创建请假审批流程示例:src/main/resources/processes/leave.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd"
id="Definitions_1" targetNamespace="http://flowable.org/processdef">
<process id="leaveProcess" name="请假审批流程" isExecutable="true">
<startEvent id="startEvent1" />
<sequenceFlow id="flow1" sourceRef="startEvent1" targetRef="approveTask" />
<userTask id="approveTask" name="经理审批" flowable:assignee="${managerId}">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler">false</modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="flow2" sourceRef="approveTask" targetRef="decision" />
<exclusiveGateway id="decision" name="审批结果" />
<sequenceFlow id="flow3" sourceRef="decision" targetRef="endEvent1">
<conditionExpression xsi:type="tFormalExpression">${approved == true}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" sourceRef="decision" targetRef="modifyTask">
<conditionExpression xsi:type="tFormalExpression">${approved == false}</conditionExpression>
</sequenceFlow>
<userTask id="modifyTask" name="修改申请" flowable:assignee="${applicantId}" />
<sequenceFlow id="flow5" sourceRef="modifyTask" targetRef="approveTask" />
<endEvent id="endEvent1" />
</process>
</definitions>
流程部署代码实现
创建流程部署服务类src/main/java/com/ruoyi/project/flow/service/ProcessDeployService.java:
@Service
public class ProcessDeployService {
@Autowired
private RepositoryService repositoryService;
/**
* 部署BPMN流程文件
*/
public AjaxResult deployProcess(MultipartFile file) {
try {
Deployment deployment = repositoryService.createDeployment()
.name(file.getOriginalFilename())
.addInputStream(file.getOriginalFilename(), file.getInputStream())
.deploy();
return AjaxResult.success("部署成功", deployment.getId());
} catch (Exception e) {
log.error("流程部署失败", e);
return AjaxResult.error("部署失败:" + e.getMessage());
}
}
/**
* 查询已部署流程列表
*/
public List<ProcessDefinition> getDeployedProcesses() {
return repositoryService.createProcessDefinitionQuery()
.latestVersion()
.orderByProcessDefinitionName().asc()
.list();
}
}
任务管理与流程交互
流程实例启动
在业务代码中启动流程实例,以请假申请为例:
@Service
public class LeaveService {
@Autowired
private RuntimeService runtimeService;
/**
* 提交请假申请,启动流程实例
*/
public String startLeaveProcess(LeaveApply apply) {
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("applicantId", SecurityUtils.getUserId()); // 当前申请人ID
variables.put("managerId", apply.getManagerId()); // 经理ID
// 启动流程实例
ProcessInstance instance = runtimeService.startProcessInstanceByKey(
"leaveProcess", // BPMN文件中定义的process id
apply.getApplyNo(), // 业务编号
variables
);
return instance.getId();
}
}
任务处理功能
创建任务审批接口,处理用户任务:
@RestController
@RequestMapping("/flow/task")
public class TaskController extends BaseController {
@Autowired
private TaskService taskService;
/**
* 完成审批任务
*/
@PostMapping("/complete")
public AjaxResult completeTask(@RequestBody TaskCompleteDTO dto) {
// 获取任务对象
Task task = taskService.createTaskQuery()
.taskId(dto.getTaskId())
.taskAssignee(SecurityUtils.getUsername())
.singleResult();
if (task == null) {
return AjaxResult.error("任务不存在或无权限处理");
}
// 设置审批结果变量
Map<String, Object> variables = new HashMap<>();
variables.put("approved", dto.isApproved());
taskService.complete(dto.getTaskId(), variables);
return AjaxResult.success();
}
/**
* 查询当前用户待办任务
*/
@GetMapping("/myTasks")
public TableDataInfo getMyTasks() {
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee(SecurityUtils.getUsername())
.orderByTaskCreateTime().desc()
.listPage(getPageNum(), getPageSize());
return getDataTable(tasks.stream().map(this::convertToVO).collect(Collectors.toList()));
}
}
前端界面集成
流程设计器集成
前端集成Flowable Modeler设计器,在Vue路由配置文件src/router/index.js中添加:
{
path: '/flow/modeler',
component: Layout,
hidden: true,
children: [{
path: 'index/:modelId',
component: () => import('@/views/flow/modeler/index'),
name: 'FlowModeler',
meta: { title: '流程设计', icon: 'form' }
}]
}
任务列表组件实现
创建待办任务列表组件src/views/flow/task/myTasks.vue:
<template>
<div class="app-container">
<el-table v-loading="loading" :data="taskList" border fit highlight-current-row>
<el-table-column type="index" label="序号" width="50" />
<el-table-column prop="name" label="任务名称" />
<el-table-column prop="processDefinitionName" label="流程名称" />
<el-table-column prop="createTime" label="创建时间" width="180" />
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleApprove(scope.row)">
处理
</el-button>
<el-button size="mini" @click="showProcessImage(scope.row)">
流程图
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
<!-- 审批弹窗 -->
<el-dialog :visible.sync="approveVisible" title="任务审批">
<el-form :model="approveForm" label-width="80px">
<el-form-item label="审批意见">
<el-radio-group v-model="approveForm.approved">
<el-radio :label="true">同意</el-radio>
<el-radio :label="false">驳回</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="意见备注">
<el-input type="textarea" v-model="approveForm.comment" rows="4" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="approveVisible = false">取消</el-button>
<el-button type="primary" @click="submitApprove">提交</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getMyTasks, completeTask } from '@/api/flow/task'
export default {
data() {
return {
loading: false,
taskList: [],
total: 0,
pageNum: 1,
pageSize: 10,
approveVisible: false,
approveForm: {
taskId: '',
approved: true,
comment: ''
}
}
},
methods: {
loadTasks() {
this.loading = true
getMyTasks({
pageNum: this.pageNum,
pageSize: this.pageSize
}).then(response => {
this.taskList = response.rows
this.total = response.total
this.loading = false
})
},
handleApprove(row) {
this.approveForm.taskId = row.id
this.approveVisible = true
},
submitApprove() {
completeTask(this.approveForm).then(() => {
this.$message.success('审批成功')
this.approveVisible = false
this.loadTasks()
})
}
},
created() {
this.loadTasks()
}
}
</script>
功能测试与问题排查
测试流程说明
- 部署流程:通过前端上传BPMN文件,调用
deployProcess接口完成部署 - 发起申请:提交请假单,调用
startLeaveProcess启动流程 - 经理审批:使用经理账号登录,在待办任务列表中处理审批
- 结果验证:检查流程状态和历史记录,确认流程按预期流转
常见问题解决方案
- 中文乱码问题:在FlowableConfig中配置中文字体,确保BPMN文件编码为UTF-8
- 流程部署失败:检查BPMN文件语法,可使用Flowable Online Designer验证
- 任务分配错误:确认流程变量传递正确,用户ID与系统用户表匹配
- 历史数据查询慢:优化ACT_HI_*表索引,调整HistoryLevel级别
扩展功能与最佳实践
流程权限控制
集成RuoYi-Vue-fast的权限系统,在任务分配时通过角色过滤候选人:
// 在用户任务分配时使用角色查询
userTask.setAssigneeExpression("${taskService.findUserByRole('DEPARTMENT_MANAGER', processInstanceId)}");
流程监控与统计
利用Flowable的HistoryService实现流程效率分析:
@Service
public class ProcessAnalysisService {
@Autowired
private HistoryService historyService;
/**
* 统计流程平均耗时
*/
public Map<String, Object> analyzeProcessEfficiency(String processKey) {
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey(processKey)
.finished();
long count = query.count();
if (count == 0) {
return Collections.emptyMap();
}
Duration averageDuration = query.list().stream()
.map(pi -> Duration.between(pi.getStartTime(), pi.getEndTime()))
.reduce(Duration.ZERO, Duration::plus)
.dividedBy(count);
Map<String, Object> result = new HashMap<>();
result.put("processKey", processKey);
result.put("averageDuration", averageDuration);
result.put("completedCount", count);
return result;
}
}
性能优化建议
- 异步任务处理:将流程中的耗时操作设计为异步服务任务
- 缓存流程定义:减少RepositoryService的查询次数
- 定期清理历史数据:使用Flowable的历史数据清理API:
managementService.deleteHistoricProcessInstancesAsync(
historyService.createHistoricProcessInstanceQuery()
.finished()
.processInstanceCompletedBefore(LocalDateTime.now().minusYears(1))
.listIds(),
"清理一年前的历史数据"
);
总结与后续学习
通过本文的步骤,你已成功在RuoYi-Vue-fast中集成Flowable工作流引擎,并实现了基础的流程定义、任务管理功能。后续可深入学习以下内容:
- 高级流程模式:如并行网关、包含网关的复杂流程设计
- 事件机制:利用Flowable的事件监听实现业务扩展
- 表单集成:结合RuoYi的表单生成器实现动态表单与流程结合
完整的集成代码已提交至项目仓库,可参考flow模块源码进一步学习。建议结合官方文档和实际业务场景,持续优化工作流功能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



