老项目升级实战:RuoYi-Vue与Flowable工作流深度整合指南
当接手一个历史遗留的RuoYi-Vue项目时,为其添加工作流支持往往成为刚需。不同于从零开始搭建新系统,老项目升级需要面对版本锁定、依赖冲突、数据迁移等一系列独特挑战。本文将分享一套经过实战检验的整合方案,特别针对非最新版RuoYi-Vue项目与Flowable工作流引擎的融合。
1. 环境评估与前期准备
1.1 项目现状诊断
在开始任何代码修改前,必须全面评估现有系统状态:
- 框架版本确认:记录当前使用的Spring Boot、MyBatis、Vue等核心框架版本号
- 依赖树分析:通过
mvn dependency:tree命令生成完整的依赖关系图 - 数据库快照:备份当前数据库结构和基础数据
- 定制功能清单:列出所有二次开发过的模块,评估与工作流的兼容性
提示:建议使用
git tag标记当前代码状态,创建专门的分支进行改造
1.2 技术选型考量
针对老项目特点,Flowable版本选择需特别注意:
| 考虑因素 | 推荐方案 | 风险提示 |
|---|---|---|
| Spring Boot兼容性 | Flowable 6.7.x系列 | 避免使用最新7.x版本 |
| 数据库支持 | 保持与原项目相同的MySQL/PostgreSQL | 注意字符集和排序规则 |
| 前端适配 | BPMN-JS 11.x | 高版本可能不兼容旧浏览器 |
2. 后端整合关键步骤
2.1 依赖管理策略
老项目改造最棘手的往往是依赖冲突问题。推荐采用分层引入方式:
- 在父POM中定义版本属性:
<properties> <flowable.version>6.7.2</flowable.version> <mybatis-plus.version>3.4.0</mybatis-plus.version> </properties>- 按模块引入必要依赖:
<!-- 核心引擎 --> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>${flowable.version}</version> <exclusions> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </exclusion> </exclusions> </dependency> <!-- 表达式支持 --> <dependency> <groupId>com.googlecode.aviator</groupId> <artifactId>aviator</artifactId> <version>5.3.3</version> </dependency>2.2 数据库适配方案
针对已有业务数据库,建议采用以下两种方案之一:
方案A:独立数据库
- 优点:完全隔离,不影响现有业务
- 缺点:跨库事务处理复杂
方案B:同库不同前缀
flowable: database-schema: FLW_ db-history-table: FLW_HISTORY_ db-identity-used: false关键配置项说明:
database-schema-update: true首次启动时设置- 连接参数添加
nullCatalogMeansCurrent=true - 字符集明确指定为
utf8mb4
3. 前端改造深度适配
3.1 组件迁移技巧
不同于简单的文件复制,老项目前端改造需要注意:
- 版本冲突解决:
# 常见冲突解决方案 npm install bpmn-js@11.1.0 --legacy-peer-deps npm install diagram-js@11.4.1 --save-exact- 样式隔离方案:
/* 在main.css中添加作用域限定 */ .flowable-container { all: initial; * { all: unset; } }3.2 路由动态注入
针对不同RuoYi-Vue版本,推荐动态路由注入模式:
// 动态检测路由类型 const isNewRouter = !!router.$addRoutes const flowableRoutes = [ { path: '/flowable', component: Layout, children: [...] } ] if (isNewRouter) { router.$addRoutes(flowableRoutes) } else { router.addRoutes(flowableRoutes) }4. 避坑实战清单
4.1 常见编译时问题
- MyBatis冲突:
// 解决方案:明确指定Mapper扫描路径 @MapperScan(value = {"com.ruoyi.**.mapper", "org.flowable.**.mapper"})- Swagger报错:
# 添加配置排除Flowable接口 springdoc: packages-to-exclude: org.flowable.rest.service.api.*4.2 运行时典型异常
- 事务失效问题:
// 正确的事务注解用法 @Transactional(transactionManager = "transactionManager") public void startProcess() { // 业务代码 }- 表单提交乱码:
# 在application.properties中添加 spring.http.encoding.force-response=true server.servlet.encoding.charset=UTF-84.3 性能优化要点
针对老项目硬件环境,特别建议:
- 流程缓存配置:
flowable: process-definition-cache-limit: 100 process-cache-enabled: true- 异步执行器调优:
@Bean public SpringAsyncExecutor asyncExecutor(DataSource dataSource) { SpringAsyncExecutor executor = new SpringAsyncExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueSize(100); return executor; }5. 数据迁移与权限整合
5.1 菜单权限处理
采用增量SQL脚本方式更安全:
-- 菜单数据迁移示例 INSERT INTO sys_menu SELECT * FROM temp_flow_menu WHERE menu_id NOT IN (SELECT menu_id FROM sys_menu);5.2 用户体系对接
实现自定义IdentityProvider:
public class CustomIdentityProvider implements IdentityService { @Override public User createNewUser(String userId) { SysUser sysUser = userService.selectUserByLoginName(userId); User flowableUser = new UserEntity(); flowableUser.setId(sysUser.getUserId().toString()); flowableUser.setFirstName(sysUser.getUserName()); return flowableUser; } }6. 验证与回归测试
建立专项检查清单:
基础功能验证:
- 流程模型部署
- 任务发起与审批
- 历史数据查询
兼容性检查:
- 原有业务接口测试
- 已有定时任务验证
- 报表导出功能确认
性能基准测试:
- 并发流程发起压测
- 长流程执行跟踪
- 内存泄漏检测
在实际项目中,我们发现最耗时的往往不是技术实现,而是历史业务数据与工作流状态的映射关系设计。建议采用"双状态"过渡方案,逐步迁移业务状态到工作流引擎中。