尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot+MySQL8+Flowable6.8.1工作流引擎落地指南

SpringBoot+MySQL8+Flowable6.8.1工作流引擎落地指南 简介一套面向Java开发者与BPM初学者的Spring Boot 2.6.13MySQL 8Flowable 6.8.1整合资源包重点解决工作流开发环境搭建繁琐、依赖版本匹配难的问题。包内自带MySQL 8安装程序降低部署门槛适合需要快速体验流程引擎、搭建可扩展企业级应用骨架或进行流程自动化改造的技术人员。资源共29个文件涵盖java源码、xml/yml配置、properties配置、jar依赖包、编译后class文件以及MySQL msi安装程序等整体382.9MB通过pom.xml可快速核对依赖版本目录结构清晰能够直接构建可运行的flowable开发环境。目前已有108人学习下载。借助这套整合包读者可以掌握Spring Boot与Flowable的集成方式、BPMN流程定义与任务管理调用方法还能利用预置MySQL安装器简化数据库初始化有效减少本地环境差异带来的排错成本。1. 一个审批流项目为什么让我把 springboot2.6.13、mysql8 和 flowable6.8.1 绑在一起前阵子要交付一个内部审批流选型定了 Flowable但版本搭配立刻成了麻烦Spring Boot 2.6.13、MySQL 8 和 Flowable 6.8.1 这三个版本号看似常规真正放到一起的时候光是把引擎的表建出来、把第一个请假流程跑通就花了我一个下午。更要命的是接手的小伙电脑上连 MySQL 8 都没有装临时下载安装又是半小时。后来我把 MySQL 8 免安装版直接放进项目目录写了一个初始化脚本让任何人拿到代码都能在十分钟内起一个可用的引擎环境。这套组合“springboot2.6.13 mysql8 flowable6.8.1自带 mysql8 安装程序”其实就是工作流引擎落地的最小可运行单元。Flowable 6.8.1 负责流程定义、任务推动和历史记录MySQL 8 负责持久化Spring Boot 2.6.13 负责把它们包成一个可维护的服务。适合谁适合要快速搭建流程中心原型的团队也适合想搞清楚 Flowable 怎么在 Spring Boot 项目里省心运行的开发者。下面按我的实际落地顺序讲先定版本再装数据库然后跑通流程最后把那些能让人血压升高的坑列出来。2. 锁定版本springboot2.6.13 与 flowable6.8.1 的依赖矩阵2.1 为什么选 2.6.13 而不是 2.7.xFlowable 6.8.1 的兼容性考量Spring Boot 2.6.13 是 2.6 这条线的收尾版本安全更新和已知问题修复都比较完整但又没有进入 2.7 之后那段“什么都升级、缓存配置全变”的折腾期。Flowable 6.8.1 官方对 Spring Boot 的支持集中在中版本它内部用到的flowable-spring-boot-starter对 Spring Boot 2.5、2.6 的自动配置机制最熟尤其对条件注解ConditionalOnMissingBean的处理比较稳。我试过在 Spring Boot 2.7 里跑 Flowable 6.8.1虽然基本流程也能动但安全过滤器的排序、自动配置的排除项都跟 2.6 有差异日志里会多出几条不痛不痒但很碍眼的 warning。如果团队没有强制升级需求留在 2.6.13 是成本最低的选择。另一个原因是 MySQL 8 在这个版本组合下驱动行为更可控。Spring Boot 2.6.13 默认管理的 MySQL 驱动是com.mysql:mysql-connector-j8.0 系列正好对应 MySQL 8 服务端。如果用旧版mysql-connector-java5.1.49连接 MySQL 8 时会直接抛认证插件不支持的异常。所以我把版本矩阵固定成三件套Spring Boot 2.6.13Flowable 6.8.1MySQL 8.0.x。这个组合的依赖关系我在真实项目里至少验证了三个月没有出现因为版本交错导致的诡异问题。2.2 最小化 pom.xml引入 flowable starter 与 mysql 驱动我用的是 Maven 项目spring-boot-starter-parent定为 2.6.13。最核心的依赖不是spring-boot-starter-web而是org.flowable:flowable-spring-boot-starter-process:6.8.1它会把引擎、流程定义管理、任务服务、历史服务全部拉进来。数据库驱动方面我直接使用 Spring Boot 依赖管理里的mysql-connector-j不需要写版本号。下面是一个能跑起流程引擎的最小pom.xml片段parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.6.13/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.flowable/groupId artifactIdflowable-spring-boot-starter-process/artifactId version6.8.1/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency /dependencies这里有两个要点。第一flowable-spring-boot-starter-process只包含流程引擎和自动配置不包含flowable-ui那套后台界面适合直接用 API 写业务。如果你还需要在线设计流程图要额外加flowable-spring-boot-starter-ui-designer但那个依赖很重新手不建议一上来就上。第二mysql-connector-j是 Spring Boot 2.6.13 中驱动的新坐标旧的mysql-connector-java虽然也能用但 Maven 会自动把它重定向到新的没必要自己写版本。2.3 版本仲裁避免 mysql-connector-java 与 mysql-connector-j 的坑很多人在这一步翻车。项目里已经有别处引入了mysql:mysql-connector-java:8.0.28再单独加com.mysql:mysql-connector-j会导致两个坐标同时存在最终复制到运行环境里只有一个 jar 但版本不确定。我见过的情况是本地跑得好好的部署到服务器上启动直接报ClassNotFoundException: com.mysql.cj.jdbc.Driver。问题不是驱动缺失而是旧协调版本被排掉了但新坐标没跟上。我的处理方式很直接只要想用 Spring Boot 2.6.13 的默认驱动管理就把项目里所有mysql-connector-java显式排除掉只保留mysql-connector-j。如果没法全局排除可以在pom.xml里用dependencyManagement强制统一版本dependencyManagement dependencies dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version /dependency /dependencies /dependencyManagement搭配mvn dependency:tree -Dincludescom.mysql看最终到底选了哪个这一步能省掉很多后面启动时的报错。版本锁定后数据源 URL 里驱动类必须写com.mysql.cj.jdbc.Driver这个类在 8.0 系列里是标准的Driver接口实现和 MySQL 8 服务端的caching_sha2_password认证插件直接兼容。3. 自带 mysql8 安装程序免安装版下载、初始化脚本与 Spring Boot 数据源3.1 免安装版 MySQL8 的下载与目录规划团队里一半人的电脑都是 Windows而且都没有数据库管理权限。让他们单独装 MySQL 8 服务端会遭遇安装向导卡住、服务启动失败、端口被占用一系列问题。所以我放弃了传统 MSI 安装直接选用 MySQL 8 免安装版zip 格式。这种包解压出来就是完整的 mysql 目录不写注册表不创建 Windows 服务适合在项目里当“本地工具”用。目录规划是这样做在项目根目录建一个tools/mysql8文件夹把解压后的bin、lib、share、support-files等文件夹放进去。注意不要直接把 zip 包提交到 Git 仓库一般会在README里写清楚去哪里下载 mysql8 免安装版然后让各人自己解压。如果必须提交记得用 Git LFS否则一个 300MB 的包会让仓库膨胀到没法用。实际上下载 mysql8 免安装版时找官网mysql-8.0.33-winx64.zip这类名字就对了下载完成后校验一下 SHA256 再解压。3.2 初始化脚本mysqld initialize-insecure 与建库建用户免安装版解压后还不能直接用必须先初始化数据目录。MySQL 8 的mysqld --initialize会生成一个随机 root 密码这在自动化脚本里很难处理。我更推荐--initialize-insecure它会生成一个 root 空密码实例脚本里可以无密码登录然后再立刻设置密码。下面是项目里的一个init_mysql.bat脚本片段它在 Windows 命令行下执行echo off set MYSQL_BIN.\tools\mysql8\bin set MYSQL_DATA.\data\mysql if not exist %MYSQL_DATA% ( %MYSQL_BIN%\mysqld --initialize-insecure --datadir%MYSQL_DATA% ) start %MYSQL_BIN%\mysqld --datadir%MYSQL_DATA% --port3306 --console timeout /t 5 /nobreak %MYSQL_BIN%\mysql -u root -e ALTER USER rootlocalhost IDENTIFIED BY root123; CREATE DATABASE IF NOT EXISTS flowable DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;逻辑说明第一步判断数据目录是否存在如果不存在就用mysqld --initialize-insecure初始化这一步会在tools/mysql8/bin所在的同级生成data/mysql目录里面包含mysql、performance_schema、sys等系统库。第二步启动mysqld注意这里用的是start它会另开一个命令行窗口跑服务避免阻塞脚本。第三步等待 5 秒后用 root 空密码进入 MySQL执行ALTER USER把密码改成root123同时创建业务库flowable。参数说明--initialize-insecure对应的老参数是--initialize --userroot如果你不习惯insecure也可以用初始化后从日志里捞临时密码的方式但脚本化不方便。--port3306要在启动和客户端连接时保持一致如果本机 3306 被占用建议改成 3307后面 Spring Boot 的 URL 也要跟着改。密码不要用root123这种太简单的至少在本地环境中换成一个只作用于开发库的密码。另外utf8mb4是必须的Flowable 的表里有注释和中文流程定义用utf8会存不下某些字符。3.3 配置 spring.datasource连接参数逐个说清MySQL 8 起来之后Spring Boot 这边的数据源配置要把驱动、URL、用户名、密码全部对好。我在application.yml里通常写下面这组配置spring: datasource: url: jdbc:mysql://localhost:3306/flowable?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: root123 driver-class-name: com.mysql.cj.jdbc.Driver flowable: database-schema-update: true history-level: auditallowPublicKeyRetrievaltrue是我建议固定写上的参数。MySQL 8 默认认证插件是caching_sha2_password在没有 SSL 加密的情况下客户端首次连接需要向服务端请求公钥如果不允许连接会直接失败。serverTimezone要明确指定不然 MySQL 会返回系统默认时区可能让java.sql.Timestamp转换出现数小时的偏移。useSSLfalse是因为本地开发环境不需要加密避免额外握手。这段配置同时开启了 Flowable 的database-schema-update: true。它的意思是启动时让 Flowable 自动创建或者升级引擎表。首次运行会创建ACT_RE_*、ACT_RU_*、ACT_HI_*等几十张表表名都是大写前缀这是 Flowable 的命名约定不要试图改成小写。后面我会说这配置在生产环境不能长期开着但在开发阶段非常省心。4. 跑通 flowable6.8.1自动建表与请假流程最小闭环4.1 引擎自动建表database-schema-update 与 history-level数据源配好后直接启动 Spring Boot 应用控制台会刷出一堆建表 SQL 日志。这是因为flowable-spring-boot-starter-process在启动时会创建一个ProcessEngine它会读取spring.flowable.database-schema-update。这里注意值不是true/false这么简单Flowable 支持true、false、create-drop、drop-create四个值其中true表示“如果需要则创建然后不再改变表结构”create-drop会在关闭时删表绝不能在开发环境用。history-level我设成audit默认实际是audit。它控制历史表的粒度none不记录任何历史activity记录流程实例和活动执行历史audit额外记录流程变量和表单属性full记录所有内容。对于审批流场景audit就够了能查“谁在什么时候提交了什么申请”不需要full产生的大量冗余数据。如果忘了配置Flowable 默认也是audit但显式写出来能让维护的人看到意图。4.2 写一个 bpmn 流程请假审批的资源与部署Flowable 的表建好后还需要一个流程图才能驱动流程实例。我把请假流程放在src/main/resources/processes/leave.bpmn20.xmlSpring Boot 启动时会自动扫描这个目录并部署到引擎。一个最简的“提交申请 - 经理审批 - 结束”流程如下?xml version1.0 encodingUTF-8? definitions xmlnshttp://www.omg.org/spec/BPMN/20100524/MODEL xmlns:flowablehttp://flowable.org/bpmn targetNamespacehttp://flowable.org/bpmn process idleaveProcess name请假审批 isExecutabletrue startEvent idstart name开始/ userTask idapply name提交申请 flowable:assignee${applyUserId}/ userTask idapprove name经理审批 flowable:assignee${approveUserId}/ endEvent idend name结束/ sequenceFlow idflow1 sourceRefstart targetRefapply/ sequenceFlow idflow2 sourceRefapply targetRefapprove/ sequenceFlow idflow3 sourceRefapprove targetRefend/ /process /definitions这个文件看起来简单但几个属性必须解释清楚。isExecutabletrue表示这个流程定义可以被引擎执行如果你从其他工具导出的 bpmn 文件里没有这个属性部署会成功但启动流程时会报“流程不存在”。userTask上的flowable:assignee指定了任务办理人它是表达式${applyUserId}会在运行时从流程变量里取值。如果你想做成候选组可以用flowable:candidateGroupsmanagers但那需要配置 Spring Boot 和 Flowable 的用户组集成最开始没必要。4.3 启动流程与完成任务Service Controller 代码有了流程定义下一步是写一个接口来发起流程、查任务、完成任务。我用RuntimeService和TaskService最顺手。下面是简化后的 Controller 代码片段RestController RequestMapping(/leave) public class LeaveController { private final RuntimeService runtimeService; private final TaskService taskService; public LeaveController(RuntimeService runtimeService, TaskService taskService) { this.runtimeService runtimeService; this.taskService taskService; } PostMapping(/start) public String start(RequestParam String applyUserId, RequestParam String approveUserId) { MapString, Object variables new HashMap(); variables.put(applyUserId, applyUserId); variables.put(approveUserId, approveUserId); ProcessInstance instance runtimeService .startProcessInstanceByKey(leaveProcess, variables); return instance.getId(); } GetMapping(/tasks) public ListTask tasks(RequestParam String userId) { return taskService.createTaskQuery().taskAssignee(userId).list(); } PostMapping(/complete) public String complete(RequestParam String taskId) { taskService.complete(taskId); return ok; } }逻辑说明startProcessInstanceByKey的第一个参数是流程定义 key对应 bpmn 里的id不是流程名称。第二个参数是流程变量它会把applyUserId和approveUserId放进流程上下文这样userTask的assignee表达式就能拿到值。查任务的时候用taskAssignee(userId)过滤这模拟了登录人看到自己的待办列表。taskService.complete(taskId)会把任务推进到下一节点如果还有后续任务 Flowable 会自动创建。参数说明这个最简接口里没有做任务认领和权限校验真实项目里至少要把taskAssignee换成任务候选组再配合 Spring Security 做身份绑定。但作为跑通闭环这三段代码足够。启动流程后你可以先调start拿到流程实例 ID再调tasks看第一个任务落在谁名下然后调complete再调一次tasks看任务是否转移到经理节点。这一步能验证工作流引擎的核心流转没有白配置。5. flowable6.8.1 mysql8 避坑排查从连接失败到建表异常5.1 连接被拒绝caching_sha2_password 与 Public Key Retrieval 问题现象是应用启动时数据源初始化报错日志里有Unable to connect to MySQL server或者Public Key Retrieval is not allowed。第一类错通常是 MySQL 8 服务没启动端口不对或者datadir路径有空格导致mysqld启动失败。第二类错是 MySQL 8 认证插件导致的它出现在用户名密码都对的情况下很反直觉。原因MySQL 8 默认的认证插件是caching_sha2_password如果不走 SSL客户端在认证握手时需要从服务端获取 RSA 公钥来加密密码。JDBC 驱动出于安全考虑默认不允许自动获取公钥所以会拒绝连接。解决在 JDBC URL 上增加allowPublicKeyRetrievaltrue参数。同时确认user表的plugin字段是caching_sha2_password还是mysql_native_password如果项目里某些老框架不支持新插件可以执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY root123;换回旧认证但我不建议这么做新驱动都能兼容caching_sha2_password。5.2 时区与字符serverTimezone 与 utf8mb4 的连锁反应现象是流程启动正常但查询历史任务时发现时间差了 8 小时或者部署流程定义时中文变量名在数据库里变成乱码。这两个问题经常一起出现但排查路径完全不同。时间问题出在serverTimezone没设。MySQL 8 服务端默认时区是系统时区如果操作系统是 CST中国标准时间JDBC 驱动拿到的时间可能包含夏令时干扰Spring Boot 里LocalDateTime序列化后又糊一层时区。解决JVM 和 JDBC URL 都统一成Asia/Shanghai并在mysqld启动参数里加--default-time-zone08:00。乱码问题出在数据库字符集。Flowable 的ACT_RU_VARIABLE表如果用了latin1排序规则流程变量里的中文会变成?。解决建库时明确CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci。如果你已经建错了库可以改库的默认字符集但已有表的列字符集不会跟着变更稳妥的做法是DROP DATABASE后重建。反正开发环境还没有业务数据早删早省心。5.3 建表失败表名大小写与数据库初始化的顺序现象是 Flowable 在启动时建表日志里突然报Table FLOWABLE.ACT_RU_TASK doesnt exist但明明ACT_RU_*已经建好了。另一个奇怪现象是同一套代码Windows 上跑得好好的Linux 上启动直接挂掉。这本质上是 MySQL 的lower_case_table_names参数在作怪。Windows 上默认值为 1表名不区分大小写Linux 上默认值为 0表名区分大小写。Flowable 生成的表名是小写但它内部某些 SQL 会引用大写表名如果在 Linux 上用严格模式就会报表不存在。解决我的习惯是在初始化 MySQL 时直接在my.ini里把lower_case_table_names设为 1。这里要特别提醒MySQL 8 要求在初始化数据目录之前就要定下这个参数否则实例启动后修改会报错甚至无法启动。所以免安装版脚本里我会在mysqld --initialize-insecure之前先写好my.ini内容大致为[mysqld] basedirC:/work/project/tools/mysql8 datadirC:/work/project/data/mysql port3306 lower_case_table_names1basedir和datadir要对准项目里实际的路径否则mysqld启动时会用默认目录找一圈然后报错。还有一点脚本初始化流程必须是“先有my.ini再跑mysqld初始化”反过来表结构和系统库已经按大小写敏感创建了再改参数就是给自己找坑。5.4 Actuator 与日志如何快速定位引擎初始化失败当你已经排除了连接、时区、大小写问题引擎还是起不来我让你直接看两处。第一处是 Spring Boot 启动日志里的Flowable相关行通常会看到FlowableActivitiAutoConfiguration或者ProcessEngineAutoConfiguration的 condition 评估。如果日志里提示某个Bean没创建就用--debug参数启动把自动配置报告打出来。第二处是直接查询库里有没有表。在应用启动前先手动执行SELECT * FROM ACT_RU_EXECUTION如果报“表不存在”说明引擎还没连接成功如果表在但启动依然报初始化失败可以把spring.flowable.database-schema-update临时设置成false让 Flowable 跳过建表逻辑只看能不能拉起引擎。这样能区分“建表脚本问题”和“引擎 Bean 初始化问题”。常见错误还有在pom.xml里同时引入flowable-spring-boot-starter-process和flowable-spring-boot-starter-rest导致两个ProcessEngine自动配置冲突日志里会出现端口占用或重复初始化。我的原则是只加一个 starter把 REST 接口自己用 Controller 写别偷懒。6. 验证与进阶用 hikari 参数和异步执行器让流程真正可用到这里基础环境已经跑通了但离“能投入小组开发”还差一步。我建议你按下面的顺序做一次完整验证。第一步启动 Spring Boot 应用后访问http://localhost:8080/leave/start?applyUserIdzhaoyiapproveUserIdmanager记录返回的流程实例 ID。第二步调/leave/tasks?userIdmanager你会在 JSON 里看到applyUserId节点生成的任务。第三步调/leave/complete?taskIdxxx再调/leave/tasks?userIdmanager发现任务列表为空而历史库里多了ACT_HI_PROCINST记录。这三步说明引擎、数据库、流程定义三者已经闭环。然后我把数据源连接池参数调了一下。Spring Boot 2.6.13 默认用 HikariCPmaximum-pool-size默认是 10对工作流引擎来说其实偏大。因为 Flowable 的异步执行器会额外拿连接如果不限制开发环境很容易把 MySQL 的连接数打满。我习惯设置spring.datasource.hikari.maximum-pool-size20同时把minimum-idle保持默认让连接池在活跃两个连接时就够用。另一个必须开的是spring.flowable.async-executor-activatetrue这个配置让 Flowable 的定时任务和异步触发器真正生效例如延时审批、超时自动提醒都依赖它。除连接池外我还有一个绕不开的教训Flowable 的监听器里不要直接调远程服务。之前我把一个流程监听器写在taskService.complete()的调用堆栈里里面同步调用外部接口结果数据库事务没提交任务已经推进了外部系统却回滚了。后来我把这种动作放到消息队列里监听器只负责发布事件Flowable 引擎的事务边界就干净了。过程中我也吃过几次滥用history-levelfull的亏生产环境一张ACT_HI_VARINST用了几个月就膨胀到几十个 G。开发阶段用audit就好。顺带一提项目里自带的 mysql8 安装程序虽然是临时方案但它让我在任何一台新机器上都能快速复现问题这个做法我保留了。每到一个新环境先跑初始化脚本再启动 Spring Boot流程必然能原地站起来。希望帮到你。本文还有配套的精品资源点击获取
返回列表