1. 项目背景与核心价值
RuoYi作为国内广泛使用的开源快速开发框架,与Flowable流程引擎的结合为企业级应用提供了标准化的工作流解决方案。这套组合拳在实际落地过程中会遇到诸多技术适配性问题,需要开发者具备跨框架的整合能力。
我在三个大型政务审批系统中成功实施了这套技术方案,累计处理超过2000个流程实例。本文将分享从环境搭建到生产部署的全链路实践经验,重点解决以下核心问题:
- 如何实现RuoYi权限体系与Flowable的身份认证无缝对接
- 动态表单与流程变量的映射策略
- 高并发场景下的历史数据归档方案
- 中国特色审批场景的特殊处理技巧
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与基础整合
2.1 版本选型关键点
经过多个项目验证,推荐使用以下稳定版本组合:
- RuoYi 4.7.5(Spring Boot 2.7.x基线)
- Flowable 7.0.0
- MySQL 8.0.28(必须启用大小写敏感)
重要提示:Flowable 7.x开始使用新的DMN决策表引擎,与6.x的API存在兼容性差异。若从旧版本迁移,需要特别注意act_ru_*系列表的字段变更。
2.2 数据库配置技巧
在application.yml中需要配置双数据源:
yaml复制# RuoYi主数据源
spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/ry?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
# Flowable工作流数据源
flowable:
datasource:
url: jdbc:mysql://localhost:3306/flowable?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: flowable
password: flowable123
实测发现两个易错点:
- Flowable数据源必须设置allowPublicKeyRetrieval=true
- 连接池建议采用HikariCP,需避免与RuoYi默认的Druid冲突
3. 权限体系深度整合
3.1 用户体系对接方案
RuoYi的用户表sys_user需要与Flowable的ACT_ID_USER表保持同步。推荐采用事件监听机制实现:
java复制@Component
public class UserSyncListener implements ApplicationListener<SysUserEvent> {
@Autowired
private IdentityService identityService;
@Override
@Transactional(transactionManager = "flowableTransactionManager")
public void onApplicationEvent(SysUserEvent event) {
SysUser user = event.getUser();
User flowableUser = identityService.createUserQuery()
.userId(user.getUserId().toString())
.singleResult();
if(flowableUser == null) {
flowableUser = identityService.newUser(user.getUserId().toString());
}
flowableUser.setFirstName(user.getUserName());
flowableUser.setEmail(user.getEmail());
identityService.saveUser(flowableUser);
}
}
3.2 部门岗位映射策略
中国特色的部门审批链需要特殊处理:
- 将RuoYi的sys_dept表映射为Flowable的ACT_ID_GROUP
- 岗位编码建议采用"deptId:postCode"的复合格式
- 实现自定义的CandidateManager扩展默认的候选组查询逻辑
4. 流程设计与动态表单
4.1 流程模型器优化
原生的Flowable Modeler需要做以下改造:
- 汉化所有按钮和提示信息
- 增加"会签节点"、"知会节点"等中国特色节点类型
- 集成RuoYi的在线表单设计器
关键代码片段:
javascript复制// 扩展自定义节点
PaletteProvider.prototype.getPaletteEntries = function() {
return {
'handtool': {...},
'zhihui-node': {
group: 'activity',
className: 'bpmn-icon-intermediate-event-catch',
title: '知会节点',
action: {
dragstart: createTask('zhihuiTask')
}
}
};
};
4.2 表单变量映射
动态表单字段与流程变量的绑定策略:
- 使用JSONB类型存储复杂表单数据
- 建立字段映射规则表:
sql复制CREATE TABLE wf_form_mapping (
form_id BIGINT NOT NULL,
field_name VARCHAR(64) NOT NULL,
variable_name VARCHAR(64) NOT NULL,
variable_type ENUM('string','number','date','json'),
PRIMARY KEY (form_id, field_name)
);
5. 高并发场景优化
5.1 历史数据分片方案
当流程实例超过10万时,需要实施:
- 按月分表:act_hi_procinst_202301
- 建立归档任务:
java复制@Scheduled(cron = "0 0 2 * * ?")
public void archiveHistoricData() {
String archiveTable = "act_hi_procinst_" + LocalDate.now().minusMonths(6)
.format(DateTimeFormatter.ofPattern("yyyyMM"));
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS " + archiveTable
+ " LIKE act_hi_procinst");
jdbcTemplate.update("INSERT INTO " + archiveTable
+ " SELECT * FROM act_hi_procinst WHERE end_time_ < ?",
Date.from(LocalDate.now().minusMonths(3)
.atStartOfDay(ZoneId.systemDefault()).toInstant()));
}
5.2 缓存策略配置
在flowable.cfg.xml中增加:
xml复制<property name="processDefinitionCache">
<bean class="org.flowable.engine.impl.persistence.deploy.DefaultDeploymentCache">
<constructor-arg value="1000"/> <!-- 缓存1000个流程定义 -->
</bean>
</property>
<property name="processInstanceCache">
<bean class="org.flowable.engine.impl.persistence.deploy.DefaultDeploymentCache">
<constructor-arg value="5000"/> <!-- 缓存5000个运行实例 -->
</bean>
</property>
6. 中国特色审批场景实现
6.1 会签节点特殊处理
需要扩展MultiInstanceActivityBehavior:
java复制public class ChineseMultiInstanceBehavior extends ParallelMultiInstanceBehavior {
@Override
public void execute(DelegateExecution execution) {
// 添加领导优先审批逻辑
if(isLeaderTask(execution)) {
createLeaderTask(execution);
} else {
super.execute(execution);
}
}
private boolean isLeaderTask(DelegateExecution execution) {
// 通过扩展属性判断是否领导节点
return Boolean.parseBoolean(
execution.getCurrentFlowElement()
.getAttributeValue("activiti:isLeader"));
}
}
6.2 审批链动态调整
实现动态审批人调整服务:
java复制public class DynamicApproverService {
public void adjustApprovers(String procInstId,
List<String> newApprovers) {
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(procInstId)
.moveActivityIdTo(currentTask.getTaskDefinitionKey(),
"adjustedUserTask")
.processVariable("overrideApprovers", newApprovers)
.changeState();
}
}
7. 生产环境部署要点
7.1 性能调优参数
在application.properties中关键配置:
properties复制# 异步执行器配置
flowable.async.executor.threads.core=20
flowable.async.executor.threads.max=100
flowable.async.executor.queue.size=500
# 历史级别配置(生产环境建议audit)
flowable.history-level=audit
# 禁用不需要的服务
flowable.idm.enabled=false
flowable.cmmn.enabled=false
7.2 监控方案实施
推荐采用Prometheus + Grafana监控:
- 添加依赖:
xml复制<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
- 配置关键指标:
java复制@Bean
public MeterBinder flowableMetrics(ProcessEngine processEngine) {
return registry -> {
new FlowableMetrics(processEngine).bindTo(registry);
new ProcessEngineMetrics(processEngine).bindTo(registry);
};
}
8. 典型问题排查指南
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 流程启动时报FormKey异常 | 表单设计器生成的key包含中文 | 在表单属性中设置英文formKey |
| 会签节点无法正确结束 | 完成条件表达式语法错误 | 使用${nrOfCompletedInstances/nrOfInstances >= 0.6}格式 |
| 任务认领后消失 | 未正确配置候选组 | 检查ACT_RU_IDENTITYLINK表数据 |
| 历史记录缺失 | 历史级别配置为none | 设置flowable.history-level=audit |
我在实际项目中总结出三个黄金检查点:
- 任何流程变更后,立即验证ACT_RE_PROCDEF表的版本号
- 用户任务异常时,首先检查ACT_RU_TASK和ACT_RU_IDENTITYLINK的关联关系
- 性能问题优先检查ASYNC_JOB_EXECUTION表的堆积情况
