资讯动态

JEECG集成Flowable:低代码平台工作流引擎落地指南

发布时间:2026/10/18 16:59:17 来源:尧图企业网站定制
简介这是一份面向 JEECG 开发者的 Flowable 工作流引擎集成源码指南适合已具备一定前后端基础、希望在 JEECG 敏捷开发平台中快速引入 BPMN2.0 工作流能力的项目团队。资源共 15 个文件、23KB包含 7 个 Java 后端核心类、前端 Vue 组件与 JavaScript 配置、YAML 和 XML 配置文件及 HTML 示例页面还附带 README 说明能覆盖从后端子工程搭建、数据库连接配置、权限对接与当前用户逻辑覆盖到前端依赖引入与组件调用的完整链路。已有 711 人学习下载。压缩包内代码示例与配置说明直接对应集成关键节点可帮助开发者在实际项目中减少摸索成本、快速实现流程审批功能并定位常见问题尤其适合作为团队内部技术预研或二次开发时的参考素材。1. JEECG集成flowable为什么低代码平台要补一个工作流引擎用JEECG搭业务系统表单、列表、权限、报表都能快速生成但客户一旦提出这个申请要走审批流程事情就变了——这套需求没法靠拖拽表单解决必须有一个真正的工作流引擎在背后跑节点、分任务、记历史。Flowable是Java生态里用得最多的BPM引擎之一把它嵌进JEECG工程正好补齐低代码平台的流程短板。下面按实际落地的顺序讲先选型摆理由再给依赖和配置然后写服务封装、表单联动和待办查询最后拆五个高频翻车点。适合正在做JEECG项目交付、被客户审批流程反复折腾的开发者。2. 集成前的架构决策选型依据、数据源归属与用户映射方案2.1 对比Activiti和Camunda之后为什么选择Flowable一句话说清楚三个引擎的来龙去脉Flowable和Camunda都是从Activiti某一代代码分出来的Activiti继续在原有体系里维护。Camunda的产品化程度最高自带了Cockpit流程监控台界面和权限体系一应俱全适合做独立部署的流程中台Activiti保持精简路线但社区活跃度近年来有所下降。Flowable夹在中间API设计得更偏开发库Engine拆分细模块可以按需引入和Spring Boot的集成封装也做得比较完整。把这三个放到JEECG集成这个具体语境里对比Camunda的问题在于引入了自己的界面层和JEECG的菜单、权限体系重复能保证不打架但维护成本高Activiti的问题是历史负担重一些老项目踩过的坑在新版本里还会遇到排查资料相对分散。Flowable从依赖数量、API稳定性、资料密度三个维度看都更适合作为嵌入模块写进JEECG。选型没有必要追求最强要追求最不容易出意外。JEECG本身的定位是快速交付低代码项目流程引擎追求的是集成路径短、踩坑有据可查。Flowable的官方文档里有专门的Spring Boot集成章节社区里也常见把它和各类快速开发平台组合使用的案例这两个条件在实际交付里非常重要。2.2 嵌入还是独立部署ProcessEngine生命周期与JEECG单体的匹配集成前要做的第一个架构决策是Flowable以什么形态跑起来。有人一提到工作流就想到单独部署一个服务让JEECG通过HTTP调用流程接口。但一旦涉及流程和业务的联动比如审批通过后修改业务状态、流程里要查业务表单数据跨服务调用就要处理分布式事务和幂等补偿复杂度会明显抬高。我一般建议在JEECG单体架构下走嵌入模式。flowable-spring-boot-starter作为普通依赖放进JEECG进程ProcessEngine和它派生的一组Service全部交给Spring容器管理。流程表和业务表落在同一个数据库、同一个事务里审批完成后更新业务表就在同一个事务内提交逻辑清楚回滚也方便。嵌入模式的代价是进程内存占用增加、后台任务和业务代码共享应用线程池。流量小时完全感觉不到流量大时可以通过给流程引擎单独调参来隔离。如果团队已经有一套独立部署的流程引擎或者有多套系统共用一套流程能力的需求再考虑独立服务。否则嵌在JEECG里是性价比最高的方案也最符合JEECG单体应用的部署习惯。2.3 ACT_表落在哪里共用数据源、表前缀与用户同步Flowable启动后会自动建立一组ACT_开头的表数量几十张按职责分成定义表、运行表、历史表和身份表。这些表放哪里决定了后续事务和备份的复杂度。JEECG支持多数据源但你不一定想把流程引擎单独开一个库因为流程表和业务表分库之后一次审批操作要跨库提交出问题就得靠补偿逻辑去追数据。更常见的做法是让Flowable的表直接落在JEECG主库里。启动时把database-schema-update设为true引擎自动建表和业务表共用一个数据库实例。备份时把ACT_前缀的表和业务表一起处理即可运维负担增加得很少。用户同步问题同样关键。Flowable自带身份模块也有一套用户表但实际项目里基本不会使用它因为审批人应当来自JEECG的机构和用户体系。用db-identity-usedfalse关掉Flowable身份模块任务分配时直接写JEECG的用户ID查询待办时用当前登录用户的ID过滤用户体系就统一了。3. 在JEECG工程里接入flowable依赖、配置与第一个流程跑通3.1 引入flowable-spring-boot-starter依赖并解决版本冲突打开JEECG工程的pom.xml加入flowable的Spring Boot Starter。多模块工程建议把工作流相关的代码和依赖收敛到一个独立模块里比如workflow模块不要让不需要流程的模块都引入引擎依赖。dependency groupIdorg.flowable/groupId artifactIdflowable-spring-boot-starter/artifactId version${flowable.version}/version /dependencyflowable.version定义在父pom的properties里选版本时注意和Spring Boot大版本对齐。Spring Boot 2.x对应Flowable 6.xSpring Boot 3.x对应Flowable 7.x一般选当前大版本里面的最新稳定版。版本对齐这事不要拍脑袋先看一眼工程里spring-boot的版本再定否则Starter内部依赖会和现有依赖发生冲突。加完依赖后最常出现jar包冲突问题。表现是服务启动到一半报BeanCreationException或者运行期某个类找不到方法日志里一堆NoSuchMethodError。排查方式是用mvn dependency:tree -Dincludesorg.flowable看依赖树再针对冲突路径用exclude排除传递依赖。常见冲突对象有jackson-databind、mybatis、commons-lang3优先保留JEECG里维护好的版本。提示依赖冲突是这类集成里最典型的玄学问题。看到NoSuchMethodError先别怀疑业务代码大概率是同一个类在classpath里有多个版本只有依赖树能告诉你真相。3.2 数据源与引擎参数配置database-schema-update、history-level怎么设依赖就位后在application.yml里加上flowable配置块。这里每个参数都直接影响集成后能否稳定运行照着示例放进去之前先理解它在当前场景里为什么这么设。flowable: database-schema-update: true history-level: audit db-identity-used: false async-executor-activate: false check-process-definitions: falsedatabase-schema-update为true表示启动时自动建表或升级表结构。开发环境这么设最省事省去手动执行建表脚本的工作生产环境建议改成false或用脚本管理升级避免引擎改动表结构引发事故。history-level设audit记录流程实例和活动实例不记录变量每次变更的明细。之前有项目图省事设成full上线三个月历史表涨到几个G查询和备份都明显变慢。流程没有强制需求时audit是成本和价值的平衡点。db-identity-used为false关掉Flowable的身份表用户数据完全依赖JEECG。这一步不做任务分配时会出现两套用户ID待办查询对不上号排查成本很高。async-executor-activate为false关闭Flowable的异步执行器。嵌入模式下后台作业扫描会占用连接池和线程小项目机器配置有限开着它容易把数据库连接耗尽。没有定时器任务或异步消息需求时这个开关保持关闭。还有一个容易忽略的资源定位配置。如果不希望BPMN文件强制放在classpath的processes目录下可以自定义扫描路径比如指定bpmn文件夹。它配合下一节的手动部署是管理多模块流程文件最可靠的方式。3.3 封装WorkflowService用JEECG风格调用发起、审批与待办查询依赖和配置完成后Spring容器里已经注册好RuntimeService、TaskService、HistoryService等组件。但Controller直接操作这些组件会耦合引擎API时间久了难以维护。常见做法是先封装一个WorkflowService把发起、审批、待办三个操作收敛成业务方法。Service public class WorkflowService { Resource private RuntimeService runtimeService; Resource private TaskService taskService; Resource private HistoryService historyService; public String startProcess(String processKey, String businessKey, MapString, Object variables) { ProcessInstance instance runtimeService .startProcessInstanceByKey(processKey, businessKey, variables); return instance.getId(); } public ListTask queryTodo(String assignee, int first, int max) { return taskService.createTaskQuery() .taskAssignee(assignee) .orderByTaskCreateTime().desc() .listPage(first, max); } public void completeTask(String taskId, MapString, Object variables) { taskService.complete(taskId, variables); } }startProcess方法里的processKey要填BPMN文件中process元素的id对应流程定义表里的KEY字段不是文件名。businessKey参数存业务表主键后续从流程实例反查业务数据就靠它。variables里放流程流转需要的字段比如金额、审批人、部门ID。completeTask的variables里建议加入approved变量值表示通过或驳回交给排他网关做分支判断。这个变量进入流程实例作用域后设计流程图时直接在网关表达式里引用即可不需要额外写判断代码。queryTodo用taskAssignee精确匹配用户适合单人任务。如果流程节点用的是候选组方式查询要换成taskCandidateGroup或taskCandidateUser。这个细节直接决定待办数据是否正确很多集成翻车都翻在这里。4. 把流程和业务表单粘在一起变量绑定、待办列表与权限过滤4.1 用BusinessKey关联业务主键避免流程变量塞满大字段流程引擎和业务表单的连接点就是发起流程时传入的那一批数据。不少开发者习惯把所有业务字段一股脑塞进流程变量再扔一个几十K的JSON字符串这是Flowable集成里最常见的坏习惯。流程变量会被持久化到运行表和历史表大字段进入后查询、备份、历史清理都会跟着变慢。通用做法是在流程变量里只保留流程决策需要的最小字段集业务表单的完整数据留在业务表用businessKey建立关联。发起流程时传业务表主键之后通过processInstanceBusinessKey可以反查流程实例需要详情数据时回到业务表取。MapString, Object vars new HashMap(); vars.put(approvalType, contract); vars.put(amount, 86000); vars.put(assignee, userId); String instanceId workflowService.startProcess(contract_approval, businessId, vars);这段代码里的businessId对应业务表主键amount用于流程里的金额网关判断assignee用于指定第一个审批节点的处理人。合同附件、备注说明这类大字段不进variables取用时按businessId回查业务表。这样变量表始终干净历史表的压力也小。4.2 待办/已办查询的常见写法和分页优化待办列表是流程功能里请求量最高的接口。单人任务用taskAssignee候选组任务用taskCandidateGroup两种任务出现在同一页面时需要用or条件组合查询。这段代码是实际项目里常用的一种写法可以直接拿来参考。public ListTask queryTodoWithOr(String userId, String groupId, int first, int max) { return taskService.createTaskQuery() .or() .taskAssignee(userId) .taskCandidateGroup(groupId) .endOr() .orderByTaskCreateTime().desc() .listPage(first, max); }or()和endOr()必须成对出现中间的条件按or关系叠加。条件本身不能为null否则会在查询阶段直接抛异常。分页用listPage传入first和max配合前端分页组件使用即可。已办查询走HistoryService按办理人加上finished条件过滤已结束的任务public ListHistoricTaskInstance queryDone(String userId, int first, int max) { return historyService.createHistoricTaskInstanceQuery() .taskAssignee(userId) .finished() .orderByHistoricTaskInstanceEndTime().desc() .listPage(first, max); }这个查询在数据量上来之后会变慢需要给Flowable历史表的常用字段建索引。重点覆盖ACT_HI_TASKINST的PROC_INST_ID_、TASK_DEF_KEY_、END_TIME_三列再配合查询条件里的assignee列。索引建在引擎自动创建的表上不冲突直接用数据库客户端执行即可。4.3 结合JEECG数据规则过滤流程实例JEECG的数据权限体系能把部门、角色范围内的数据过滤掉但这个能力作用在业务表上流程实例表不在它的直接管辖范围内。如果不加处理任何登录用户都可能通过流程接口看到其他部门发起的流程。常规做法是发起流程时把发起人所在部门写入流程变量查询流程实例时先从JEECG数据规则里拿到当前用户可见的部门集合再拼到流程实例查询的条件里。Flowable对流程实例的变量过滤有原生支持String deptId currentUser.getDeptId(); ListProcessInstance instances runtimeService.createProcessInstanceQuery() .variableValueEquals(deptId, deptId) .list();如果部门集合较多可以用variableValueIn(deptId, deptIds)一次传入列表。变量过滤依赖ACT_RU_VARIABLE表这张表和ACT_RU_EXECUTION表的关联字段需要建索引否则流程数量上来后查询会明显变慢。这是接入阶段容易被忽视的调优点。5. 集成flowable最容易翻车的五个地方现象、原因与解决方案5.1 启动后数据库连接池被后台任务占满业务表查询变慢现象服务正常跑一段时间后业务接口响应从几十毫秒涨到几秒日志里大量出现无法获取连接数据库连接数监控打满。原因Flowable的异步执行器默认开启会在作业表里持续扫描定时任务和事件消息。嵌入模式下和JEECG业务共享数据库连接池两边同时抢连接池子不够用就出现上面的现象。解决集成初期先关闭异步执行器把配置里的async-executor-activate设为false。同时让Flowable和JEECG复用同一个数据源不要新建第二个DataSource指向同一个库。如果业务确实需要定时器任务等基础跑通之后单独评估开启并调大连接池的最大连接数。5.2 部署了BPMN文件流程定义列表却为空现象把BPMN文件放进了resources目录服务也启动成功了但流程定义列表里一条记录都查不到。原因Starter默认只在classpath的processes目录下扫描流程文件。多模块工程里文件如果放在业务模块的资源目录而Flowable在公共模块启动扫描路径就命不中。另外不配置resource-locations时自定义目录里的文件不会被自动部署。解决不依赖自动部署改为手动部署部署路径自己控制。在应用启动监听器或者初始化方法里执行repositoryService.createDeployment() .addClasspathResource(bpmn/contract_approval.bpmn20.xml) .name(合同审批流程) .deploy();如果文件比较多也可以用自定义配置统一扫描flowable: resource-locations: classpath*:/bpmn/**/*.bpmn20.xml注意两种方式不要混用。手动部署配合版本管理上线时流程版本更可控是我个人更倾向的方式。5.3 审批通过以后业务表状态纹丝不动现象流程顺利走到结束节点页面上显示流程已完成但打开业务表单审批状态还停留在待审核。原因流程引擎只负责流转审批完成不会自动改业务表。集成方少了一环更新业务状态的动作这是最常见的工作流认知盲区。解决把状态更新逻辑挂到节点事件上。推荐在流程图的最后一个人工节点结束位置挂一个ExecutionListener或者在流程末尾增加一个ServiceTask在其中调用JEECG的业务Service把状态改成已同意或已驳回。这段逻辑要放进Spring事务里监听器抛出异常时整个流程回滚保证流程数据和业务数据始终一致。5.4 历史数据膨胀到影响查询清理又怕丢轨迹现象流程上线几个月后ACT_HI_ACTINST、ACT_HI_VARINST表越来越大流程追踪页面打开要等好几秒数据库备份也明显变慢。原因history-level设成full导致每次流程变量变更都留下多版本记录。加上没有建立历史数据清理机制只增不减数据量积累到一定程度就拖垮查询。解决把新流程的history-level调整到audit减少单实例的数据量。对已经堆积的历史数据写一个定时任务定期删除已结束流程的历史记录调用HistoryService的removeHistoricProcessInstance。删除前必须确认流程实例已经结束否则引擎会抛异常。保留时长按业务需求定一般保留180天比较常见。5.5 服务重启后待办任务的处理人全部对不上现象发布新版本后用户打开待办中心任务数量看起来正常但点进去发现处理人和当前登录用户对不上有的任务别人能看自己看不了。原因任务分配时写死了另一套用户标识。例如流程设计器里配置了具体的用户账号或者流程变量里放的是姓名而不是JEECG用户ID导致待办查询按登录ID过滤时匹配不上。这个问题在重启后才暴露是因为重启前任务已经分配完毕用户没有往这个方向核对过。解决流程设计时不要写死用户用户节点全部使用${assignee}这类表达式由发起流程的代码动态传入JEECG用户ID保持db-identity-usedfalse。发布新版本前做一次人工核对用管理员账号跑一遍流程确认任务能正确分配给目标用户再对外发布。6. 进阶技巧用历史活动实例把流程足迹画回页面流程跑通之后业务方第一个追问就是现在走到哪一步了、谁审的、审了多久。这些数据在Flowable历史服务里都有现成接口不需要自己建表记录。一组查询拿回活动节点的时间线和处理人前端按顺序展示就是一个完整的流程追踪模块。public ListHistoricActivityInstance trace(String processInstanceId) { return historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime().asc() .list(); }返回的记录对应流程图里的每个节点包含节点类型、名称、开始结束时间、办理人。前端拿到后按用户任务节点和网关节点分组展示用户任务显示处理人和耗时网关节点折叠不显示。这样一个审批进度面板就出来了视觉效果和商用流程系统基本一致。还有一个高频需求是当前节点高亮。BPMN模型在RepositoryService里完整存储读取出来之后渲染到前端画布根据trace结果找到当前活动节点打上标记。这一步主要工作量在前端数据来源就是上面这个trace方法。如果前端团队不太熟悉BPMN渲染建议先用表格形式展示进度等稳定了再考虑画布高亮。这套集成做下来我最深的体会是不要一上来就铺全量功能先把一条最简流程从发起到审批走完验证待办、已办、业务状态都对得上再往上加并行网关、会签、子流程。每加一种流程结构都回归一次数据一致性。流程引擎一旦上了生产追数据的成本比设计阶段多花的时间高得多。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑