ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot 3集成Flowable 7实战:从部署到完成任务全流程

Spring Boot 3集成Flowable 7实战:从部署到完成任务全流程 我最近在给一个内部管理系统补审批流技术栈定的 Spring Boot 3.x调研了一圈工作流引擎最后选了 Flowable 7.x。真动手才发现网上关于 Spring Boot 集成 Flowable 的教程绝大部分还停留在 Flowable 6 Spring Boot 2 的老组合上照着抄很容易在启动阶段就被 javax 和 jakarta 的包名变更卡住。这篇文章就把我从零开始集成 Spring Boot 3.x 与 Flowable 7.x并跑通设计流程、部署流程、发起流程、完成任务这一条主线的完整过程记录下来给同样在这条路上踩坑的朋友一个可以直接参考的版本。内容定位很明确不聊复杂的会签、驳回、多实例只聚焦一个最小可用的请假审批流程。适合两类人看一是刚接触 Flowable、想知道这东西到底怎么落到 Spring Boot 项目里的新手二是从老版本迁移过来、需要确认 Spring Boot 3 适配细节的老手。我会把选型原因、环境搭建、BPMN 设计、核心 API 调用以及我实际踩到的坑都写出来。1. 为什么选 Flowable 7.xSpring Boot 3 的 Jakarta 迁移与引擎选型1.1 Flowable 6 与 7 的分水岭javax 到 jakartaSpring Boot 3.0 发布时做了一件影响面非常大的事底层从 Java EE 切换到 Jakarta EE 9所有原本以javax.*开头的包名全部改成了jakarta.*。这对普通业务代码影响不大但对工作流引擎这种深度依赖 Servlet、事务、验证等 Java EE 规范的中间件来说几乎是颠覆性的。Flowable 6.x 是为 Spring Boot 2.x 和 javax 生态准备的。你如果强行把 Flowable 6.x 塞进 Spring Boot 3.x 工程最常见的报错是ClassNotFoundException: javax.servlet.Filter或者各种NoClassDefFoundError: javax/xml/bind/JAXBException。原因就是 Spring Boot 3 应用里压根不存在 javax 包你引入的 Flowable 6 代码却还在按老包名找类。这不是配置能解决的必须换引擎版本。Flowable 7.x 是官方第一个完整适配 Spring Boot 3 的版本线底层切换到 jakarta 命名空间同时要求 Java 17 及以上。所以如果你的项目基线已经是 Spring Boot 3.2 Java 17Flowable 7 几乎是必然选择。版本号上我本地用的是 7.1.0读者可以换成官方 7.x 的最新稳定小版本坐标和用法都一样。1.2 Flowable、Activiti、Camunda 的取舍提到工作流引擎绕不开三个名字Activiti、Flowable、Camunda。它们同宗同源早期都脱胎于 JBoss 的 jBPM 项目后来分道扬镳。我在选型时做了这么几个维度的对比维度Flowable 7ActivitiCamunda 7/8Spring Boot 3 适配原生支持更新节奏偏慢7 可适配8 架构变化大社区活跃度高文档齐全中高轻量嵌入 Spring Boot很好starter 完善一般7 好8 偏向独立部署周边组件表单、DMN、CMMN、IDM较少流程设计器体验好说实话Camunda 的流程设计器在交互体验上确实有优势但 Camunda 8 主推的 Zeebe 引擎是云原生架构面向微服务、独立集群部署的场景对在现有单体系统里嵌入一个审批引擎这种需求来说太重了。Camunda 7 倒是轻量但它和 Spring Boot 3 的适配没有 Flowable 那么顺滑。Activiti 这些年迭代节奏慢社区里新内容也少。Flowable 的另一个优势是flowable-spring-boot-starter做得比较完善依赖一加、配置一写引擎就自动起来了和 Spring 的事务、数据源天然集成。对于标题里集成、部署、发起、完成这一条链路Flowable 的 API 设计也是最直白的学习成本相对低。最后我定的方案就是 Spring Boot 3.2.x Flowable 7.1.0 H2 内存库先跑通后续再切 MySQL。2. 环境搭建IntelliJ 社区版也能快速跑通 Spring Boot 3 Flowable 72.1 没有 Spring Initializr 的 IDEA 社区版怎么起项目很多人用 IntelliJ IDEA 社区版但社区版不内置 Spring Initializr 向导这是新手最容易卡住的第一关。其实不必纠结直接打开浏览器访问 https://start.spring.io 这是一个官方的 Spring Boot 项目生成器选择构建工具 Maven、语言 Java、Spring Boot 版本选 3.2.x 或更高Group 填com.exampleArtifact 填flowable-demo依赖先勾选Spring Web和H2 Database点击 Generate 下载 zip 压缩包下载完解压在 IDEA 社区版里直接File - Open选择解压后的目录识别为 Maven 项目即可。这一步不需要任何额外插件社区版完全能胜任。这里有一个小提示生成的项目 Java 版本默认是 17和 Spring Boot 3、Flowable 7 的 Java 版本要求完全匹配不需要手动改。如果你的本地 JDK 还是 8 或 11请先升级否则后面编译期就会报错。2.2 引入 flowable-spring-boot-starter 的正确姿势项目骨架起来之后打开pom.xml在dependencies里加两个东西Flowable 的 Spring Boot Starter 和 H2 驱动。H2 驱动在 Initializr 勾选后会自动生成如果没有就手动补dependency groupIdorg.flowable/groupId artifactIdflowable-spring-boot-starter/artifactId version7.1.0/version /dependency dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency注意这个 starter 有两个可选坐标这里值得展开说一下flowable-spring-boot-starter全家桶会同时启动 Process 引擎、CMMN案例管理、DMN决策表、App 引擎以及 Flowable 自带的 IDM 身份管理模块。启动时会创建一大批表对于只想用流程的人来说有点重。flowable-spring-boot-starter-process只启动流程引擎不包含 CMMN/DMN/IDM表更精简启动更快。如果你确定只需要审批流我建议直接用flowable-spring-boot-starter-process。但第一篇为了和大多数教程保持一致、避免某些功能缺失导致排查困难我先用全家桶 starter 演示。等跑通了再换精简版验证一遍也不迟。另外提醒一下Flowable 7 的 starter 会自动带出flowable-engine、flowable-spring、flowable-spring-boot-autoconfigure等核心模块不需要你逐个手动引入避免版本不对齐。这就是 Spring Boot Starter 机制的意义。2.3 最小配置H2 内存库与 Flowable 自动建表开关依赖加好后在src/main/resources/application.yml里写如下配置spring: datasource: url: jdbc:h2:mem:flowable;DB_CLOSE_DELAY-1 driver-class-name: org.h2.Driver username: sa password: h2: console: enabled: true path: /h2-console flowable: database-schema-update: true async-executor-activate: true这段配置里每行都有讲究。jdbc:h2:mem:flowable;DB_CLOSE_DELAY-1表示创建一个名为 flowable 的内存数据库DB_CLOSE_DELAY-1保证 JVM 不退出前数据库不会因为最后一个连接关闭而自动销毁否则 Flowable 引擎初始化到一半数据库没了会出各种诡异问题。spring.flowable.database-schema-update: true是让 Flowable 在启动时自动对比引擎需要的表结构和现有数据库缺失就自动建表。开发阶段这个配置非常省心但生产环境务必改成false改用数据库脚本手动管理表结构避免引擎在正式库上乱操作。async-executor-activate: true是开启 Flowable 的异步执行器。简单流程暂时用不到但后面一旦引入定时器事件、异步消息这个开关就是必须的现在打开可以少折腾一次。spring.h2.console是 H2 提供的网页管理端浏览器访问http://localhost:8080/h2-console填入同样的 JDBC URL 和账号密码就能直接看到 Flowable 建出来的所有表排查问题非常有用。3. 引擎启动后自动建表和核心 Service Bean 验证3.1 启动日志里有哪些关键信息配置写好直接运行启动类。Spring Boot 的启动日志里会多出几行 Flowable 相关的记录我自己实测时关注的主要是这几个控制台出现Flowable Engine created字样说明流程引擎初始化成功。日志中穿插大量CREATE TABLE ACT_GE_BYTEARRAY类似的建表语句说明database-schema-updatetrue生效了。如果日志里出现Deployment ... was deployed之类的记录说明 Flowable 扫描到了 classpath 下的流程文件并执行了自动部署。这一条后面专门讨论。这几点全部出现恭喜引擎已经活了。3.2 认识 ACT_ 系列数据表Flowable 的行为建立在几十张数据库表上表名全部以ACT_开头按用途分四个前缀这里列一下后面排查问题全靠它们前缀含义代表性表用途ACT_RE_Repository静态资源ACT_RE_DEPLOYMENT、ACT_RE_PROCDEF部署记录、流程定义ACT_RU_Runtime运行时数据ACT_RU_EXECUTION、ACT_RU_TASK、ACT_RU_VARIABLE运行中的实例、任务、变量ACT_HI_History历史数据ACT_HI_PROCINST、ACT_HI_TASKINST已结束/进行中的流程历史ACT_ID_Identity身份数据ACT_ID_USER、ACT_ID_GROUP用户、用户组ACT_GE_General通用数据ACT_GE_BYTEARRAY二进制资源如 BPMN 文件内容理解这些表的分类对排查问题很重要。比如你发起了一个流程但任务没出现先查ACT_RU_TASK看任务是否存在流程实例结束没看ACT_RU_EXECUTION里还有没有记录如果流程报错但没有异常堆栈翻ACT_HI_ACTINST的结束时间能定位卡在哪个节点。我实测中最常用的组合是ACT_RU_TASK查当前待办ACT_HI_PROCINST查整个流程生命周期的起止时间ACT_GE_BYTEARRAY查部署进去的 BPMN 文件原始内容。这三张表就能覆盖 90% 的排障需求。3.3 注入引擎服务并写第一个测试Flowable 的 Spring Boot 自动配置会向容器里注册一堆核心 API Bean最常用的有五个RepositoryService部署和管理流程定义、RuntimeService启动流程实例、TaskService查询和完成任务、HistoryService查询历史数据、IdentityService用户和组管理。为了验证引擎真的可用我写了一个最小的测试类。在src/test/java下创建FlowableSmokeTest.javaimport org.flowable.engine.RepositoryService; import org.flowable.engine.repository.Deployment; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; SpringBootTest class FlowableSmokeTest { Autowired private RepositoryService repositoryService; Test void contextLoads() { long count repositoryService.createDeploymentQuery().count(); System.out.println(当前部署数量: count); } }这个测试什么都没干只验证两点容器能正常启动说明 Flowable 自动配置没有报错、RepositoryService能正常注入和查询说明引擎核心 API 可用。如果这一步过了后面部署、发起、完成任务就有基础了。4. 设计请假流程从需求到一份可部署的 BPMN 文件4.1 需求到流程元素事件、用户任务、排他网关先明确我们的演示流程是什么。需求非常简单员工提交请假申请如果请假天数小于等于 3 天经理审批即可如果超过 3 天需要总监审批。这个流程麻雀虽小五脏俱全覆盖了 BPMN 2.0 中最核心的几类元素开始事件流程的起点用一个圆圈表示。用户任务需要人工审批的环节对应填写请假申请经理审批总监审批。排他网关根据条件选择唯一出口天数判断就是一个排他网关。顺序流连接各个节点的箭头上面可以写条件表达式。结束事件流程的终点。使用 Flowable 建模时每个用户任务可以指定办理人。指定方式有三种分别是固定值、表达式、候选组。这里在填写请假申请节点我用了表达式${applicant}意思是流程变量applicant的值就是办理人经理审批节点直接写死字符串manager总监审批节点写死director。后面用代码发起流程时只要把applicant变量传进去Flowable 就会自动把第一个任务分配给对应的人。4.2 一份可直接部署的请假流程 BPMNFlowable 的流程定义文件本质是一个标准的 BPMN 2.0 XML 文件后缀通常是.bpmn20.xml或.bpmn。我建议直接手工维护一份简单 XML理解每一步的含义。下面是我实际用过的请假流程文件完整贴出来?xml version1.0 encodingUTF-8? definitions xmlnshttp://www.omg.org/spec/BPMN/20100524/MODEL xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:flowablehttp://flowable.org/bpmn targetNamespacehttp://www.flowable.org/processdef process idleaveProcess name请假审批流程 isExecutabletrue startEvent idstartEvent name申请开始/ sequenceFlow idflow1 sourceRefstartEvent targetRefapplyTask/ userTask idapplyTask name填写请假申请 flowable:assignee${applicant}/ sequenceFlow idflow2 sourceRefapplyTask targetRefgateway/ exclusiveGateway idgateway name请假天数判断 defaultflowToManager/ sequenceFlow idflowToManager sourceRefgateway targetRefmanagerApprove name小于等于3天 conditionExpression xsi:typetFormalExpression ![CDATA[${leaveDays 3}]] /conditionExpression /sequenceFlow sequenceFlow idflowToDirector sourceRefgateway targetRefdirectorApprove name大于3天 conditionExpression xsi:typetFormalExpression ![CDATA[${leaveDays 3}]] /conditionExpression /sequenceFlow userTask idmanagerApprove name经理审批 flowable:assigneemanager/ sequenceFlow idflow3 sourceRefmanagerApprove targetRefendEvent/ userTask iddirectorApprove name总监审批 flowable:assigneedirector/ sequenceFlow idflow4 sourceRefdirectorApprove targetRefendEvent/ endEvent idendEvent name结束/ /process /definitions注意两个实战细节。第一排他网关的defaultflowToManager很重要它指定了默认出口。当所有条件表达式都无法正确求值时比如leaveDays变量缺失流程会走默认出口而不是直接抛异常。很多新手在这里踩坑网关条件没设置 default变量稍微传错整个流程就报错中断。第二这个文件里我没有写 BPMN 的 DI 图形信息即每个节点的坐标位置因为引擎部署执行时完全不依赖坐标Flowable 会自动按顺序执行。如果你要把这个文件导入 Flowable Modeler 或 IDEA 的 BPMN 可视化插件重新排版工具会提示缺少 DI自动生成布局后另存即可。4.3 resources 目录策略自动部署还是手动部署把这份 XML 文件放到src/main/resources/bpmn/leave.bpmn20.xml目录名特意不叫processes这是有原因的。Flowable 的 Spring Boot Starter 默认会扫描 classpath 下的processes/目录找到所有.bpmn和.bpmn20.xml文件并自动部署。这个机制在开发时很好用但和本篇文章要演示的通过 RepositoryService 手动部署 API会形成两条部署路径你放在 processes 下的文件每次启动都会被自动部署一遍再看手动部署的结果就会在流程定义表里看到多个版本容易把初学者搞晕。所以我这里把文件放在bpmn/目录避开默认扫描路径然后通过代码显式部署。这样整个演示链路是单一路径逻辑清晰。关于自动部署的更多细节我在 6.4 节专门展开。5. 三行代码走完流程部署、发起、完成任务的全链路演示5.1 部署流程定义RepositoryService 与 DeploymentBuilder部署在 Flowable 中的含义是把 BPMN 文件包成一个 Deployment 对象写入ACT_RE_DEPLOYMENT表同时解析出流程定义写入ACT_RE_PROCDEF表。之后发起流程时引擎才能根据流程定义的 key 找到对应的定义。部署代码非常简单注入RepositoryService后调用构建器Autowired private RepositoryService repositoryService; public String deployLeaveProcess() { Deployment deployment repositoryService.createDeployment() .addClasspathResource(bpmn/leave.bpmn20.xml) .name(请假流程) .deploy(); return deployment.getId(); }部署完成后可以查一下流程定义确认版本号ProcessDefinition processDefinition repositoryService.createProcessDefinitionQuery() .processDefinitionKey(leaveProcess) .latestVersion() .singleResult(); System.out.println(流程定义ID: processDefinition.getId()); System.out.println(流程定义版本: processDefinition.getVersion());这里processDefinitionKey(leaveProcess)对应 XML 里process idleaveProcess的 id不是文件里的 name。同一个 key 每部署一次版本号就加 1latestVersion()可以拿到最新版本。第一版部署后版本是 1。5.2 发起流程实例RuntimeService 与流程变量流程定义是模板流程实例才是按照模板跑起来的一次具体业务。比如所有请假都共享leaveProcess这个定义但张三请 2 天假和李四请 5 天假就是两个独立的流程实例。发起流程的代码Autowired private RuntimeService runtimeService; public String startLeaveProcess(String applicant, int leaveDays, String businessKey) { MapString, Object variables new HashMap(); variables.put(applicant, applicant); variables.put(leaveDays, leaveDays); ProcessInstance processInstance runtimeService .startProcessInstanceByKey(leaveProcess, businessKey, variables); return processInstance.getId(); }startProcessInstanceByKey有三个关键传参第一个是流程定义 key第二个是业务主键 businessKey第三个是流程变量 Map。businessKey 建议传业务系统的单号比如请假单号LEAVE-20250101-001这样之后在历史表中可以很方便地反查这个流程实例对应哪条业务记录。流程变量是这次发起流程的核心。XLM 里flowable:assignee${applicant}会取applicant变量作为办理人网关条件${leaveDays 3}和${leaveDays 3}会取leaveDays变量做判断。如果发起时不传这两个变量第一个任务的 assignee 是空字符串网关默认走 manager 审批整个流程行为就完全不是设计的样子。发起之后可以立即用 TaskService 查询当前生成的任务ListTask tasks taskService.createTaskQuery() .processInstanceId(processInstanceId) .orderByTaskCreateTime().asc() .list();此时tasks里应该只有一个填写请假申请任务办理人是张三。5.3 完成任务并推动流程TaskService 使用流程实例发起后停在第一个用户任务上接下来要通过 TaskService 完成任务流程才能继续往下走。完成的本质是告诉引擎这个人工节点的工作结束了引擎随后会沿顺序流走到网关根据变量判断出口。第一个任务完成Task applyTask taskService.createTaskQuery() .processInstanceId(processInstanceId) .taskAssignee(张三) .singleResult(); taskService.complete(applyTask.getId());完成之后网关会根据leaveDays的值选择走向。我测两组数据张三请 2 天假网关走小于等于3天分支此时任务列表中应该出现经理审批办理人是 manager。李四请 5 天假网关走大于3天分支此时任务列表中应该出现总监审批办理人是 director。经理审批完成Task managerTask taskService.createTaskQuery() .processInstanceId(processInstanceId) .taskAssignee(manager) .singleResult(); taskService.complete(managerTask.getId());再查询当前任务列表应该为空说明流程已经走到结束事件。Flowable 对于简单的串行流程任务完成后引擎会自动推进到下一个节点直到遇到下一个用户任务或到达结束事件。这里要特别说明taskAssignee的用法。XML 中经理节点 assignee 是固定字符串manager所以查询时用.taskAssignee(manager)精准定位。如果 assignee 写的是zhangsan这样的用户名这里就传对应用户名。5.4 用历史表验证流程是否真的走完完成了完成任务不代表能确认流程内部状态是健康的我习惯用 HistoryService 做最终验证确认整条流程确实走到了结束事件HistoricProcessInstance historicProcessInstance historyService .createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); System.out.println(流程结束时间: historicProcessInstance.getEndTime());如果getEndTime()不为 null说明流程实例已正常结束。这个字段为 null 则代表流程还在运行中去ACT_RU_TASK看当前卡在哪个任务上即可。这里顺便讲一个看表技巧流程结束后ACT_RU_EXECUTION和ACT_RU_TASK里对应记录会消失因为运行时表只保存进行中的数据而ACT_HI_*系列表会永久保留这条流程的完整轨迹。这也是历史表名字里 HI 的含义。如果查不到历史流程实例大概率是发起流程时用的 processInstanceId 不对或者流程事务回滚了。6. 实测中的坑与建议版本冲突、事务、变量序列化与自动部署6.1 Jakarta 包冲突与经典报错我在刚开始集成时踩过最典型的坑就是同时引入了老版本的流程引擎依赖。当时工程里原先有一个内部工具包传递依赖带入了flowable-engine:6.7.x结果和flowable-spring-boot-starter:7.1.0的引擎类冲突。症状是启动时一堆NoSuchMethodError、ClassNotFoundException且错误信息里的包名在 javax 和 jakarta 之间反复横跳。排查方式很简单执行 Maven 依赖树分析mvn dependency:tree -Dincludesorg.flowable如果看到同一个org.flowable组件出现两个版本就说明依赖冲突了。解决方案是在pom.xml里排除旧版本只保留 Flowable 7 的传递依赖或者排除掉引旧引擎的内部工具包。我的建议是以 Flowable 7 的 BOM 为准参考官方文档把 starter 放在内部工具包之前声明Maven 就近声明原则会优先采用显式的 7.1.0 版本。另外一个典型的 Spring Boot 3 报错是org.springframework.beans.factory.BeanCreationException错误提示找不到某个javax.*的类。这种基本就是某个老组件不是为 Jakarta 设计导致的和 Flowable 6 的问题同源。处理方式是一致的要么升级组件到支持 Spring Boot 3 的版本要么放弃这个组件没有别的捷径。6.2 事务让业务操作和流程状态保持一致Flowable 集成到 Spring Boot 后引擎默认使用应用的数据源和 Spring 的PlatformTransactionManager。这意味着你可以把业务操作和流程操作放在同一个事务里。比如提交请假申请这个动作通常要干两件事向业务表插入一条请假单记录然后调用 RuntimeService 发起流程实例。如果这两步不在同一个事务里可能出现请假单插入成功但流程发起失败的数据不一致反过来也一样。正确做法是在 Service 方法上加TransactionalTransactional public void submitLeave(LeaveForm form) { leaveMapper.insert(form); runtimeService.startProcessInstanceByKey(leaveProcess, form.getId(), form.toVariables()); }这里有个值得说的机制runtimeService.startProcessInstanceByKey内部会参与当前 Spring 事务如果事务回滚流程实例的创建也会一并回滚。Flowable 的 Spring 集成把引擎命令包装成了SpringTransactionInterceptor使引擎操作和业务操作共用同一个事务上下文。这一点在写生产代码时必须注意别把流程操作甩在业务事务外面。反过来也提醒一句Flowable 自己的事务传播行为在 Spring Boot 下不需要额外配置但如果你同时操作多个数据源务必认真确认Transactional的transactionManager是 Flowable 正在用的那个否则会陷入业务库提交了、流程库回滚了的诡异状态。6.3 流程变量的类型选择与序列化问题流程变量是 Flowable 里传数据的主要手段但实际用起来有隐藏门槛。基本类型String、Integer、Long、Boolean、Date会被直接存到ACT_RU_VARIABLE表里没有问题如果你传入的是一个自定义 Java 对象比如LeaveFormFlowable 默认会用 JDK 序列化把它变成字节数组存到ACT_GE_BYTEARRAY表里。这个设计在演示阶段没问题但在生产环境会让你吃大亏只要实体类改了字段或包名历史流程里存的反序列化对象就可能爆炸而且ACT_RU_VARIABLE里查询时拿到的只是一个带byte[]的记录想按对象属性做条件查询也做不了。我的建议是流程变量只放流程路由需要的最小数据集例如申请人、请假天数、审批金额、业务主键。真正完整的业务数据放在业务表里流程通过 businessKey 关联回去。这样既保证网关表达式能顺畅求值又不会把流程引擎变成业务数据容器。如果实在需要复杂对象可以考虑定义一个 DTO 并实现Serializable同时在变量名前加前缀避免和系统内置变量混淆。这里再提一个热词里出现的flowable:collection它是 Flowable 在多实例任务中指定集合变量的属性用于实现会签、或签等场景。本文的简单流程不涉及后面的系列文章我会专门展开讲多实例和集合变量的配合方式。6.4 开发与生产环境的自动部署策略Flowable 引擎在启动时会扫描 classpath 下的processes/目录自动部署其中的流程文件。这个机制有两面性值得仔细设计开发环境把 BPMN 文件放在resources/processes/下每次改完 XML重启应用就自动部署新版本省去手动调 API 的麻烦非常适合快速迭代。生产环境应该关闭自动部署统一走发布流水线。否则每次重启服务所有进程定义都会被重新部署一遍版本号不断叠加ACT_RE_PROCDEF里堆满内容相同的低版本定义既占空间又容易让人误判当前线上跑的是哪个版本。关闭自动部署的配置spring: flowable: check-process-definitions: false关掉之后流程定义的生命周期完全由你控制的部署脚本管理。实际项目中我们有一套简单的发布脚本Spring Boot 应用启动后执行一个部署命令把本次发布包内的 BPMN 文件批量部署上去比依赖自动扫描更可控。还有一个隐藏细节即使开启了自动部署Flowable 也会比较 BPMN 文件内容内容完全相同时并不会真的新建部署记录而是复用原有部署。这个机制避免了很多重复部署的浪费但也有例外——如果你手工调用 DeploymentBuilder 部署完全相同的内容版本号依然会叠加所以演示时我特意把文件放在bpmn/目录避免和自动部署机制叠加产生干扰。6.5 从简单流程走向真实业务下一步可以扩展什么跑通本文的最小流程后你已经可以把 Flowable 真正用起来了。但说实话真实业务场景很少有这种一路顺风的审批流后面大概率会碰到这些需求监听器想在任务创建、任务完成、流程结束时触发一段业务逻辑比如发通知、写日志可以用 Flowable 的执行监听器和任务监听器。会签与或签一个审批节点需要多个人同时审批或者任意一人通过即可对应 BPMN 里的多实例活动。驳回与退回审批不通过时回到上一节点需要结合网关和边界事件设计。请假天数这类变量的权限控制谁能在哪个节点修改哪个流程变量需要引入 Flowable 的权限模型或结合 Spring Security。表单集成把 Flowable 的动态表单和前端表单打通实践中大多数团队会直接用前端表单把表单数据通过流程变量传给引擎。我个人的体会是Flowable 是一把好刀但一开始别急着追求复杂模型的炫技。先把部署、发起、完成任务、历史查询这几条链路的运行原理吃透后面加会签、加监听器的时候你会发现自己能很自然地推断出引擎在每一步做了什么、数据写到了哪张表。这也是我把系列第一篇文章控制在这个范围的原因。下一篇我会接着写监听器与多实例任务也就是会签的实现方式。
返回列表