
简介本资源是基于 RuoYi-Vue-Plus 二次开发、扩展 Flowable 工作流能力的后台管理项目面向需要在线表单设计与可视化流程编排的 Java 开发者尤其适合学习工作流引擎、毕业设计及企业后台原型搭建等场景。压缩包共 1198 个文件约 10.81MB以 502 个 Java 后端源码、248 个 JavaScript 与 132 个 Vue 前端组件为主体辅以 53 个 XML 配置、26 个 SQL 脚本、18 个 Velocity 模板及若干样式、字体与部署脚本覆盖前后端与数据库完整链路。目前已有 2369 人学习下载。项目采用 MIT 开源协议个人与企业均可免费使用脚手架功能同步 RuoYi-Vue-Plus 更新读者可据此理解 Flowable 与在线表单的集成方式、流程定义与业务表单的绑定思路并借助现成目录结构快速搭建可运行的工作流后台用于学习与二次开发参考。1. 从若依脚手架到 Flowable 工作流二次开发到底在扩什么很多团队选 RuoYi-Vue-Plus 做后台图的是权限、代码生成、多租户这些开箱即用的能力但真到业务落地绕不开审批流。请假、报销、合同会签、工单流转这些场景用状态机硬编码能撑一阵流程一改就得动代码、重新发版运维和业务两头受气。于是「基于 RuoYi-Vue-Plus 二次开发扩展 Flowable 工作流」成了高频需求热搜里 flowable 快速入门、工作流编码、在线表单设计反复出现说明大家卡的不是「要不要上工作流」而是「怎么在已有脚手架上把它接进去、表单怎么让业务自己配」。这篇讲的就是这条路径在 RuoYi-Vue-Plus 的工程结构里嵌入 Flowable 引擎把流程定义、任务办理、在线表单设计串成一条能跑通的链路。适合已经用过若依、手上有一版后台系统、准备把审批能力做成平台化组件的后端和全栈同学。读完你应该能判断这套方案值不值得投入以及第一步该动哪些模块。2. 在 RuoYi-Vue-Plus 里接入 Flowable 的工程改造2.1 为什么不是直接引依赖就完事Flowable 本身是个独立引擎官方 starter 能让你几分钟跑起一个 demo但 RuoYi-Vue-Plus 有自己的多数据源、权限体系、统一返回体和 Sa-Token 鉴权。直接引flowable-spring-boot-starter会带来几个现实问题引擎默认自己建表、自己管事务和若依的数据源路由打架任务查询接口默认按引擎用户体系走和若依的SysUser对不上流程相关的表如果和业务表混在一个库多租户隔离会很难做。常见做法是把 Flowable 的表单独放一个数据源或者至少用独立的前缀区分然后在配置里关掉引擎的自动建表改用官方 SQL 脚本手动初始化这样升级和备份都可控。我一般会新建一个ruoyi-flowable模块依赖ruoyi-common把引擎配置、任务服务、表单服务都收在这里业务模块只依赖它的接口不直接碰引擎 API。2.2 依赖与数据源的落地配置先看依赖核心是 Flowable 的 Spring Boot starter 和它需要的几个模块。版本上跟随 RuoYi-Vue-Plus 主版本用的 Spring Boot 大版本走别自己乱升否则 MyBatis-Plus 和引擎的事务管理器容易冲突。!-- ruoyi-flowable/pom.xml 片段 -- dependency groupIdorg.flowable/groupId artifactIdflowable-spring-boot-starter-process/artifactId version6.8.0/version /dependency !-- 需要表单引擎时再加 -- dependency groupIdorg.flowable/groupId artifactIdflowable-spring-boot-starter-form/artifactId version6.8.0/version /dependency数据源配置是第一个坑点。若依默认用 dynamic-datasourceFlowable 的ProcessEngineConfiguration需要明确指定 DataSource否则它会去抢主数据源。# application-flowable.yml flowable: # 关闭自动建表用官方脚本手动初始化避免每次启动校验表结构 database-schema-update: false # 关闭异步执行器自动激活按需在业务里控制 async-executor-activate: false # 历史级别audit 够用full 会明显增大存储 history-level: audit # 关闭引擎自带的 IDM 用户体系统一走若依的 SysUser idm: enabled: false配置里database-schema-update: false是关键生产环境绝不能让引擎自己改表。history-level选audit是性价比最高的档位能查历史任务和变量又不像full那样把每次变量变更都存一份。idm.enabled: false关掉后任务分配就得自己接管这正是我们要做的——把 Flowable 的 assignee 映射到若依的 userId。2.3 把若依用户体系接到 Flowable 任务上引擎默认的IdentityService管用户和组但我们的用户数据在sys_user里。有两种接法一是实现IdmIdentityService做适配二是干脆不用引擎的用户查询任务分配时直接写若依的 userId 字符串查询时用若依的权限过滤。第二种更轻我一般选它。Service public class FlowTaskService { Autowired private TaskService taskService; // 办理任务同时写入业务变量 public void complete(String taskId, String userId, MapString, Object variables) { // 先校验当前用户是否有权办理该任务 Task task taskService.createTaskQuery() .taskId(taskId) .taskAssignee(userId) .singleResult(); if (task null) { throw new ServiceException(任务不存在或无权办理); } // 添加审批意见Flowable 用 comment 存 taskService.addComment(taskId, task.getProcessInstanceId(), 审批通过); taskService.complete(taskId, variables); } }这段代码里taskAssignee(userId)就是映射点userId 直接存若依的用户 ID。addComment把审批意见写进ACT_HI_COMMENT前端查审批记录时读这张表。注意complete的 variables 会作为流程变量持久化别塞大对象否则历史表膨胀很快。参数上taskId来自前端待办列表userId从 Sa-Token 的登录上下文取不要信前端传的用户身份。3. 在线表单设计让业务自己配而不是每次改代码3.1 表单和流程的绑定关系怎么设计在线表单设计是这套方案里最容易被低估的部分。很多人以为表单就是前端拖拽生成 JSON存起来渲染就行但和 Flowable 结合后核心问题是表单数据存在哪、流程变量怎么和表单字段对应、不同节点能不能看到不同字段。常见做法是建两张表wf_form存表单定义JSON schemawf_form_data存表单实例数据用process_instance_id关联流程实例。流程启动时把表单数据里需要参与条件判断的字段同步成流程变量比如金额、部门、类型。这样网关条件表达式可以直接用${amount 5000}这种写法而不用去查业务表。表单 schema 建议用一套固定的结构前端渲染和后端校验都基于它避免各写各的。{ fields: [ { key: amount, label: 报销金额, type: number, required: true, processVar: true }, { key: reason, label: 事由, type: textarea, required: true, processVar: false } ] }processVar标记这个字段是否要同步成流程变量。只有参与条件判断或需要在流程中读取的字段才标 true其余留在表单数据表里减少流程变量数量。这个设计能明显降低历史表的压力也是我踩过坑之后的习惯。3.2 表单数据的保存与回显表单实例数据的读写要跟流程实例生命周期对齐。启动流程时先存表单数据拿到 ID再作为变量传给引擎任务办理时按 taskId 找到对应的表单数据回显。Transactional(rollbackFor Exception.class) public String startProcess(String formKey, MapString, Object formData, String userId) { // 1. 保存表单数据 WfFormData data new WfFormData(); data.setFormKey(formKey); data.setFormData(JSON.toJSONString(formData)); data.setCreateBy(userId); formDataMapper.insert(data); // 2. 提取需要作为流程变量的字段 MapString, Object vars extractProcessVars(formKey, formData); vars.put(initiator, userId); vars.put(formDataId, data.getId()); // 3. 启动流程实例 ProcessInstance instance runtimeService.startProcessInstanceByKey(formKey, vars); data.setProcessInstanceId(instance.getId()); formDataMapper.updateById(data); return instance.getId(); }extractProcessVars根据表单 schema 里的processVar标记过滤字段不要整个 formData 都塞进变量。formDataId作为变量存进去后续节点就能通过它反查完整表单。事务注解不能少表单保存和流程启动必须同成功同失败否则会出现流程起来了但表单没存的黑匣子情况。3.3 节点级字段权限的控制同一个表单在不同审批节点可见和可编辑的字段往往不同。比如申请人能改金额审批人只能看不能改。这个控制放在表单 schema 的节点配置里而不是硬编码在页面。配置项含义示例nodeKey流程节点标识deptLeaderAuditvisibleFields可见字段 key 列表[amount,reason]editableFields可编辑字段 key 列表[]requiredFields必填字段 key 列表[reason]前端拿到当前 taskId 后调后端接口取该节点的字段权限配置再决定渲染成只读还是可编辑。后端在complete之前也要按同样的配置校验一次防止绕过前端直接调接口改字段。这个双端校验是血泪经验只做前端控制等于没做。4. 流程设计器的选型与前后端对接4.1 用 bpmn-js 还是自己画流程设计器这块主流选择是 bpmn-js它是 BPMN 2.0 的前端建模库Flowable 的 XML 能直接导入导出。自己从零画节点连线不是不行但 BPMN 的网关、边界事件、子流程这些语义太复杂重造轮子成本极高。bpmn-js 配合 flowable 的 moddle 扩展能支持flowable:assignee、flowable:candidateGroups这些自定义属性。集成时注意版本匹配bpmn-js 的 flowable 扩展包要和引擎的 BPMN 版本对齐否则导出的 XML 里自定义属性会丢。我一般把设计器做成独立路由页面保存时把 XML 字符串传给后端后端用repositoryService部署。// 前端保存流程定义 async function saveProcess(xml, processKey, processName) { const res await request({ url: /flowable/definition/save, method: post, data: { xml, processKey, processName } }); return res.data; }xml是 bpmn-js 导出的完整 BPMN 字符串后端不要做字符串拼接直接交给引擎解析。processKey要和 XML 里的process id一致否则部署后按 key 启动会找不到。4.2 后端部署流程定义的接口部署是流程上线的入口要处理版本管理。同一个 key 重复部署Flowable 会自动升版本旧版本实例继续按旧定义走这是引擎自带的后悔药别自己再搞一套版本表。public String deploy(String xml, String processKey, String processName) { Deployment deployment repositoryService.createDeployment() .name(processName) .addString(processKey .bpmn20.xml, xml) .deploy(); // 返回部署 ID前端可用于展示 return deployment.getId(); }addString的资源名必须以.bpmn20.xml结尾否则引擎不识别。processKey作为文件名前缀只是习惯真正决定启动 key 的是 XML 里的 process id。部署后可以用repositoryService.createProcessDefinitionQuery().deploymentId(...)查定义详情把版本号返回给前端展示。4.3 待办、已办、我发起的三个列表怎么查任务列表是用户接触最多的界面查询逻辑要分清三个维度。待办是taskAssignee或候选组匹配当前用户已办查历史任务表HistoricTaskInstance我发起的查HistoricProcessInstance里startUserId等于当前用户的。// 待办查询含候选组 public ListTask todoList(String userId, ListString roleIds) { return taskService.createTaskQuery() .taskCandidateOrAssigned(userId) .taskCandidateGroupIn(roleIds) .orderByTaskCreateTime().desc() .list(); }taskCandidateOrAssigned同时覆盖直接指派和候选组两种情况roleIds从若依的角色体系取。注意候选组存的是角色 ID 字符串要和若依的角色编码保持一致否则查不到。分页用引擎自带的listPage别全查出来再内存分页数据量上来会拖垮服务。5. 避坑与排查那些让流程卡住的真实问题5.1 流程启动报「no processes deployed with key」现象是调启动接口直接抛异常日志里说找不到对应 key 的流程定义。原因通常是部署时 XML 里的 process id 和启动时传的 key 不一致或者部署根本没成功。排查时先查ACT_RE_PROCDEF表看KEY_字段有没有你要的值没有就回去看部署接口的返回和 XML 内容。解决方式是统一用 XML 里的 process id 作为启动 key部署后加一步校验查不到定义就抛明确错误。5.2 任务办理后流程没往下走现象是调了 complete任务消失了但流程停在原地或者直接结束。原因多半是网关条件表达式没匹配上Flowable 默认走第一条符合条件的连线如果所有条件都不满足且没有默认流流程会卡住或报错。排查看ACT_RU_EXECUTION表里当前执行实例停在哪再对照 BPMN 里网关的 conditionExpression。解决是给排他网关配一条默认流条件用${amount 5000}这种明确表达式变量名和表单同步的字段名严格一致。5.3 表单数据保存了但流程变量取不到现象是流程走到条件网关时判断结果不对或者表达式报变量不存在。原因是表单字段的processVar没标 true或者同步变量的代码在启动流程之后才执行。排查时在启动流程前打印 vars 的内容确认字段都在。解决是把变量提取放在startProcessInstanceByKey之前并且表单 schema 里参与判断的字段必须标processVar: true。5.4 历史表数据暴涨导致查询变慢现象是系统跑几个月后待办和已办列表越来越慢。原因是history-level设成了full或者流程变量里塞了大文本。排查看ACT_HI_DETAIL和ACT_HI_VARINST的行数。解决是把历史级别降到audit流程变量只存必要字段大文本留在业务表里用 ID 关联。已经产生的历史数据可以按时间归档别直接删合规上可能还要留痕。5.5 多租户下流程实例串数据现象是 A 租户的用户能看到 B 租户的待办。原因是 Flowable 的表没有租户字段查询时没加租户过滤。排查时看任务查询有没有带租户条件。解决是在流程变量里存tenantId所有任务查询都加.processVariableValueEquals(tenantId, currentTenantId)或者用 Flowable 自带的租户 ID 机制在部署和启动时传入 tenantId查询时用taskTenantId。后者更规范但需要改造部署接口。6. 进阶把流程能力做成可复用的平台组件走到这一步流程能跑通了但离「平台化」还差一层。真正省事的做法是把流程能力抽象成几个稳定的接口业务模块只调接口不碰引擎。我一般会定义ProcessFacade暴露start、complete、queryTodo、queryHistory四个方法内部封装引擎细节。这样以后换引擎版本、加审批人动态计算、接消息通知都只改 facade 内部。动态审批人是另一个高频需求。固定 assignee 写死在 BPMN 里业务一调整就得重新部署。常见做法是用flowable:assignee${approver}在启动或完成任务时把approver作为变量传进去值由业务侧的审批人计算服务给出。这样流程定义不用动审批人规则在代码里配。验证这套方案是否真的可用我习惯做三件事一是用一条最简单的请假流程跑通启动到结束确认引擎和若依的鉴权、数据源都对二是故意把网关条件写错看报错信息是否清晰、能不能快速定位三是压一批并发启动观察历史表和连接池的表现。这三步过了再往业务里铺。最后说个习惯每次改 BPMN 或表单 schema先在测试环境部署一个新版本用旧实例和新实例各跑一遍确认版本隔离没问题再上生产。Flowable 的版本机制是后悔药但前提是你别把旧版本的部署记录删了。这套东西投入不大一个后端加一个前端两三周能出可用版本值不值得做看你的审批场景是不是会频繁变。希望帮到你。本文还有配套的精品资源点击获取