尧图精选

Spring Boot 3 集成 Camunda 7:工作流引擎实战指南

🕒 发布时间:2026/9/20 14:26:03 📁 来源:尧图网络
简介这是一份基于 Spring Boot 3.X 整合 Camunda 的工作流引擎项目源码面向需要快速搭建流程审批、任务管理类功能的 Java 后端开发者。资源采用 Maven 多模块结构拆分为 server 与 client 两个子模块便于理解服务端与调用端的职责划分源码中包含 Camunda 核心配置、BPMN 流程定义文件、业务接口示例以及相关 XML 映射可直接导入 IDE 运行调试。压缩包共 87 个文件以 java、xml、bpmn、yml 等类型为主包体仅 1.17MB轻量紧凑。从文件组成来看项目还附带 Git 版本记录与 README 说明适合作为学习和二次开发基础。已有 300 人学习下载适合具备一定 Spring Boot 基础、希望掌握 Camunda 集成方式的开发者参考。 工作流引擎这个词对 Java 后端来说是个既熟悉又陌生的东西。熟悉是因为一提审批流、工单流转、状态机绕不开 Camunda、Flowable、Activiti 这几家陌生是因为很多项目组压根没正经在 Spring Boot 里从零整合过一套完整的流程引擎最多是看过文档、跑过 demo。这次我在一个 Spring Boot 3.2 的项目里完整落地了 Camunda从版本选型到 BPMN 建模再到核心 API 调用和线上问题排查都走了一遍。这篇就按我的实操顺序来梳理从配置到跑通第一个流程再到把你一定会遇到的坑提前踩平。文章里用的版本是Spring Boot 3.2.x Camunda 7.20的组合。这是目前社区版里和 Spring Boot 3.x 配合最成熟的一套基于 Java 17内嵌式部署不需要额外起单独的流程引擎服务。有一定 Spring Boot 基础的开发者可以照着做完整个集成新手也能通过这篇了解工作流引擎在你项目里到底扮演什么角色。1. 版本选型Spring Boot 3.x 里的 Camunda 不是随便选的很多人在第一步就栽跟头。看到 Spring Boot 3.x脑子一热去 Maven 搜 Camunda 最新版结果引入一堆和 Spring Boot 2.x 时代完全不同的依赖。这里有个大前提Camunda 从 7.x 到 8.x 是两套完全不同的架构。7.x 是传统的 Java 库直接嵌进你的 Spring Boot 应用共享数据库连接池和事务8.x 是基于 Zeebe 的云原生架构通常要独立部署 BrokerSpring Boot 应用只作为客户端远程调用。选哪个取决于你的部署环境但如果你想整合也就是把引擎跑在 Spring Boot 进程内那么 Camunda 7 是合理选择版本上从 7.19 开始才完整支持 Spring Boot 3.x 的 Jakarta 命名空间。1.1 Camunda 7 和 Camunda 8 的区别先搞清楚再动手我见过不止一个同事把 Camunda 8 的 Spring Boot Starter 加到项目里结果启动直接报错找不到javax.persistence。原因是 Camunda 8 的 Spring Boot Starter 默认假设你连接的是 Zeebe Gateway而不是本地数据库整个交互模型完全不同。简单说如果你的场景是在现有 Spring Boot 单体应用里加一套可嵌入的流程引擎流程定义存在数据库表里用 Java API 直接操作就选 Camunda 7。如果你的场景是微服务架构流程引擎需要独立扩展、独立部署通过 REST 或 gRPC 和业务服务解耦那才考虑 Camunda 8。1.2 引入依赖和基础配置一步到位Spring Boot 3.2 项目的 pom.xml 中核心依赖就两个dependency groupIdorg.camunda.bpm.springboot/groupId artifactIdcamunda-bpm-spring-boot-starter/artifactId version7.20.0/version /dependency dependency groupIdorg.camunda.bpm.springboot/groupId artifactIdcamunda-bpm-spring-boot-starter-rest/artifactId version7.20.0/version /dependency第一个 starter 是引擎本体第二个 starter-rest 会暴露一组 REST API方便前端或外部系统通过 HTTP 操作流程。如果你的项目不需要 REST 接口第二个可以不引入但实际开发中建议加上Camunda 自带的 Cockpit 和 Tasklist Web 应用在很多场景下调试流程非常方便。配置文件里核心是数据源和自动部署开关我在application.yml里是这样配的spring: datasource: url: jdbc:mysql://localhost:3306/camunda_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver camunda: bpm: admin-user: id: admin password: admin123 first-name: Admin filter: create: All tasks auto-deployment-enabled: true database-schema-update: true history-level: fulladmin-user会自动创建一个管理员账号用于登录 Camunda 自带的 Web 应用auto-deployment-enabled设为 true 后Spring Boot 启动时会自动扫描classpath:/processes目录下的.bpmn文件并部署database-schema-update设为 true 表示启动时自动创建或更新引擎需要的 40 多张表history-level建议直接设 full后面查历史流程和性能分析都靠它。注意Camunda 7 和 Spring Boot 3.x 搭配时务必将database-schema-update设为 true 首次启动否则会因为缺少ACT_GE_PROPERTY等核心表直接抛异常。2. 画一个请假审批流程部署到 Spring Boot引擎跑起来只是第一步真正要落地的是流程本身。我不建议一上来就写代码先在 Camunda Modeler 里把流程图设计好导出 bpmn 文件再放到 Spring Boot 工程里自动部署。2.1 用 Camunda Modeler 设计 BPMN 流程Camunda Modeler 是 Camunda 官方出品的桌面建模工具支持 BPMN 2.0 标准拖拽节点就能画图。以一个最常见的请假审批流程为例设计整条链路开始事件用户提交请假申请用户任务填写请假单Assignee 设为${requester}排他网关判断请假天数是否大于 3 天如果大于 3 天走经理审批任务Assignee 设为manager结束事件流程结束导出后的 bpmn 文件里会看到 XML 结构定义了流程的每个节点和它们之间的连线。核心结构大致是这样bpmn:process idleaveProcess name请假审批流程 isExecutabletrue bpmn:startEvent idstartEvent / bpmn:userTask idapplyTask name填写请假单 camunda:assignee${requester} / bpmn:exclusiveGateway idgatewayCheckDays name天数判断 / bpmn:userTask idmanagerApproveTask name经理审批 camunda:assigneemanager / bpmn:sequenceFlow idflow1 sourceRefstartEvent targetRefapplyTask / !-- 每个节点和连线都要有对应的 sequenceFlow 定义 -- /bpmn:process注意一点BPMN 文件里的process id是流程定义的唯一标识后面调 API 启动流程时靠的就是这个 id所以设计时要慎重一般用驼峰命名比如leaveProcess、orderFlow这种。2.2 自动部署机制的原理把 bpmn 文件放到src/main/resources/processes目录下重启 Spring BootCamunda 会自动读取并部署。但它不是简单地每次启动都重复部署一遍而是比较流程定义的 key 和版本号。同一个 key 的流程如果 bpmn 文件内容有变化会生成一个新的版本历史流程依然走旧版本新发起的流程走最新版本。这个版本管理机制在实际项目中很重要。线上流程已经在跑了你改了一版 bpmn不能影响进行中的实例只有新发起的流程才用新版定义。Camunda 的部署器天然支持这个逻辑你不需要写额外的代码只要把新版 bpmn 放进去重启即可。3. 核心 API 实操从启动流程到完成任务部署只是起点业务系统真正要调的是 Camunda 提供的 Java API。整个操作流程分三块启动流程实例、查询并完成任务、处理网关条件。我在代码里直接在一个 Service 类里串起来你可以直接抄。3.1 启动流程实例业务数据和流程变量绑定启动流程时业务系统通常要传递业务单号、操作人、请假天数这些数据。Camunda 提供了流程变量机制可以在启动时设置也可以在流程执行过程中动态添加。以下是我项目里的一个典型写法Service public class LeaveProcessService { Autowired private RuntimeService runtimeService; Autowired private TaskService taskService; public String startLeaveProcess(String requester, int days) { MapString, Object variables new HashMap(); variables.put(requester, requester); variables.put(days, days); ProcessInstance instance runtimeService .startProcessInstanceByKey(leaveProcess, BIZ- System.currentTimeMillis(), variables); return instance.getProcessInstanceId(); } }startProcessInstanceByKey传入三个参数流程定义的 key、业务键、流程变量。业务键也可以是业务系统里的申请单号这样后续你要查询某个业务单号的流程实例可以直接通过runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(BIZ-10001).singleResult()查回来比记流程实例 ID 方便得多。3.2 查询待办任务别用错 TaskQuery流程启动后就会在填写请假单这个用户任务上停住。比如前端页面上要给张三展示他待办的任务后端就是走 TaskService 查询。这里有一个非常容易用错的点taskAssignee是查指定办理人的任务taskCandidateUser是查候选人的任务这两个概念不能混淆否则查出来的结果会漏掉。推荐写法public ListTask getTodoTasks(String assignee) { return taskService.createTaskQuery() .taskAssignee(assignee) .active() .orderByTaskCreateTime() .desc() .list(); }查询结果里task.getProcessInstanceId()是流程实例 IDtask.getId()是任务 ID注意区分。任务 ID 是在完成任务时要用的关键参数而流程实例 ID 是跨任务一直存在的全局标识。3.3 完成任务并设置网关判断变量填写请假单任务完成时需要把请假天数作为流程变量传进去后面的排他网关会根据days的值决定走经理审批还是直接结束。完整代码如下public void completeApplyTask(String taskId, int days) { MapString, Object variables new HashMap(); variables.put(days, days); taskService.complete(taskId, variables); }BPMN 里的排他网关会自动读取这个days变量和连线条件做比较bpmn:conditionExpression xsi:typebpmn:tFormalExpression ${days 3} /bpmn:conditionExpression这里的关键是条件表达式用的是 Spring EL 语法变量名要和传入的变量名完全一致类型也要匹配。我遇到过一个问题业务方传的days是字符串5表达式里写days 3结果网关直接抛异常找了好久才定位到类型不匹配。建议在入口处统一做类型校验和转换。4. 踩坑实录我用 Camunda 时遇到的四个典型问题集成 Camunda 的过程中有几个问题是反复出现的我在各个社区和群里也看到不少新手在问。这里把最典型的四个问题整理出来都是你一定会遇到的。4.1 启动报错数据库连接失败或表不完整首次启动如果报错信息里出现Error querying database或者Table ACT_GE_PROPERTY doesnt exist基本就是数据源配置有问题或者database-schema-update没设成 true。MySQL 要注意的细节很多比如时区配置、字符集配置、驱动版本。Spring Boot 3.x 默认用 MySQL Connector/J 8.xURL 里必须带上serverTimezoneAsia/Shanghai否则会报时间相关的 SQL 异常。4.2 流程图里的中文乱码Camunda 自带的 Cockpit 里查看流程定义图中文乱码是常见现象尤其是 Linux 服务器上。原因是 JVM 找不到中文字体。解决办法是在启动参数里加上-Dfile.encodingUTF-8然后在服务器上安装中文字体比如执行yum install fontconfig后把 Windows 的 simhei.ttf 拷贝到/usr/share/fonts目录下才能保证绘制流程图时中文不会变成方块。4.3 事务一致性问题流程推进和业务数据不能脱节Camunda 7 的 API 默认会参与 Spring 事务。比如创建请假单并启动流程这个过程如果业务数据保存失败了流程实例也必须回滚否则就会出现业务单没建成功但流程已经跑起来了的脏数据。真正稳妥的做法是把两步操作放在同一个事务方法里Transactional(rollbackFor Exception.class) public void createAndStartProcess(String requester, int days) { leaveOrderMapper.insertOrder(...); runtimeService.startProcessInstanceByKey(leaveProcess, ...); }如果在事务外部调用流程 API或者监听了流程事件后在监听器里操作业务库出现数据不一致的概率会大很多。我的经验是能用 Spring 事务包住引擎调用的地方就尽量包住不要信任好像大多数时候没问题。4.4 任务查询出现性能瓶颈时的优化任务表ACT_RU_TASK是引擎里增长最快的表之一随着流程实例增多慢查询会越来越明显。一个常用的优化手段是按业务键和创建时间的联合条件去查避免全表扫描另一个是定期清理已完成流程的运行时数据把历史归档到ACT_HI_*表。我在项目里配置了一个定时任务每天凌晨清理 30 天前已结束的流程实例执行的是 Camunda 提供的HistoryService删除接口historyService.deleteHistoricProcessInstance(processInstanceId);这个操作会同步清理运行时数据和历史数据但生产环境操作前一定要确认流程确实已经结束否则会误删活跃流程。5. 从 Flowable 迁移到 Camunda 的体验补充项目早期用的是 Flowable因为公司内部有一段历史代码基于 Flowable 开发。这次新项目换成 Camunda 后我有几个切身的感受。一个是 API 设计风格不同。Flowable 把很多操作封装在RuntimeService和TaskService里但细节上有差异比如查询任务的排序方式、变量传递的时机都需要重新适应。Camunda 的查询 API 更直观尤其是TaskQuery提供了完整的链式条件想按候选人、业务键、流程定义 key 组合查询都很顺手。另一个是社区氛围和文档质量的差别。Camunda 的官方文档对 BPMN 2.0 规范和 Spring Boot 集成的覆盖更细致遇到的绝大多数问题都能在文档里找到答案。Flowable 的文档也不错但某些底层逻辑讲得没那么透。如果你在 Spring Boot 3.x 项目里从零开始选型我个人建议是直接上 Camunda 7。它和 Spring Boot 3.x 的兼容性、社区活跃度、版本迭代速度目前来说都更让人放心。6. 一点个人经验总结从画 BPMN 流程图到跑通完整链路我觉得最值得反复揣摩的不是 API 怎么调而是流程引擎在你的系统里到底负责什么。很多团队把流程引擎当成万能钥匙把各种业务规则都塞进流程节点里结果流程图画得极其复杂维护成本直线飙升。我的做法是流程引擎只负责流转和人机交互业务规则的判断放在代码里通过流程变量传递给网关条件这样既灵活又不会让流程图失控。另外一个建议是开发阶段把 Camunda 自带的 Web 应用Cockpit 和 Tasklist开起来尤其是通过camunda-bpm-spring-boot-starter-webapp引入后你就能在浏览器里直观看到每个流程实例跑到哪个节点、停留多久、变量是什么。排查问题的时候比看日志高效得多。最后再说个小细节history-level如果不是full历史任务查询和流程实例报告的数据会不完整后面做统计报表时才发现就晚了。我当时图省事设成了audit结果要查某个任务的变量快照时发现查不到翻文档才发现只记录了流程级别的数据。这个配置建议在一开始就定好。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →