资讯动态

Flowable / 芋道 BPM 面试要点

发布时间:2026/8/22 17:35:49 来源:尧图企业网站定制
Flowable / 芋道 BPM 面试要点摘要本文全面梳理了基于芋道 BPM底层 Flowable 6.8.0的工作流面试要点。内容涵盖简历表述与开场总述、芋道 BPM 三层架构与核心链路、流程定义部署/实例发起/任务审批/审批人策略/会签或签/业务回调等具体实现、流程与业务状态一致性保障、单人审批与审批组区别、网关分流实现、常见问题速答。重点深入分布式场景下的状态同步、并发处理、补偿对账机制以及微服务架构下的最终一致性方案。适用于准备 BPM/工作流相关面试的开发者快速掌握核心知识点。基于芋道源码yudao-module-bpm整理一、简历表述1. 专业技能一句话工作流引擎熟悉 Activiti、Flowable 流程引擎基于芋道 BPM 实践流程定义部署、实例发起与任务审批掌握审批人策略、会签/或签及业务单据事件回调集成。2. 系统项目经历一句话基于 Flowable/芋道 BPM为报废、计量计划、折旧及采购订单/合同/验收等业务接入审批流通过流程发起 API 与状态事件回调实现单据审批与业务状态联动。二、开场总述3060 秒我们项目的审批是基于芋道 BPM底层用 Flowable。整体是三层前端设计器画流程后端 Service 编排真正执行靠 Flowable 的 Repository / Runtime / Task 这些 API。业务系统不直接调引擎而是通过统一的发起 API用 businessKey 关联业务单审批结束后通过 Spring 事件回调把通过/拒绝状态写回业务表。审批人怎么找是用策略模式按角色、部门、发起人等规则算出来的。面试提示简历写 Activiti/Flowable 均可落地引擎是 Flowable概念与 Activiti 同源API 和 BPMN 高度相似。三、芋道 BPM 架构速记引擎与版本运行时引擎Flowable 6.8.0非 Activiti / Camunda独立模块yudao-module-bpm分层结构Controller定义/实例/任务/OA → Service业务编排 → Flowable APIRepository / Runtime / Task / History → 扩展层审批人策略、自定义 Behavior、事件监听、自建扩展表核心链路环节实现部署模型发布 →RepositoryService部署 BPMN扩展信息写入bpm_process_definition_info发起BpmProcessInstanceApi→RuntimeService按流程 Key 启动businessKey关联业务单审批通过/拒绝/退回/转办/加签 →TaskService回调引擎事件 → SpringBpmProcessInstanceStatusEvent→ 业务 Listener 回写状态设计亮点可点名策略模式审批人规则角色/部门/发起人/表单字段/表达式等可插拔自定义 Behavior覆盖 UserTask支持会签/或签/依次审批业务解耦业务只依赖 API 状态事件不直接碰 Flowable双设计器BPMN 仿钉钉 SimpleJSON 转 BPMN模块已接入流程业务流程 Key报废oa_scrap_application计量计划device_metering_plan折旧记录oa_depreciation_record采购订单oa_purchase_order采购合同oa_contract验收oa_acceptance_process四、按能力点怎么答「具体实现」1流程定义部署流程在设计器里画好BPMN 或仿钉钉的 Simple 模型。发布时后端把模型转成 BPMN调用RepositoryService做 Deployment同时把表单类型、图标、发起权限等扩展信息存到自己的扩展表。部署后按流程 Key 找最新激活版本来发起。关键词Deployment、ProcessDefinition、流程 Key、扩展表2实例发起两种入口管理端页面发起或业务模块调BpmProcessInstanceApi。传入流程定义 Key、发起人、变量、businessKey。Service 里用RuntimeService按 Key 启动最新定义并把processInstanceId回写到业务单。关键词createProcessInstance、businessKey、流程变量标准接入四步先落业务单调 API 发起流程带 businessKey、变量回写 processInstanceId实现状态事件 Listener按 Key 更新业务状态3任务审批待办在 Task 表里。用户点通过时Service 先记审批意见和状态再调TaskService.complete拒绝、退回、转办、委派、加签也是在 TaskService 能力上再封装一层业务规则。用户身份会塞进 Flowable 的 Authentication保证发起人、审批人记录正确。关键词approve / reject / return / transfer / complete4审批人策略Flowable 默认指派比较简单芋道用自定义ActivityBehaviorFactory覆盖 UserTask 行为。真正算审批人时走策略模式按配置选「角色 / 部门负责人 / 指定用户 / 发起人自选 / 表单字段」等策略算出候选人再挂到任务上。新增一种找人规则主要是加一个 Strategy不用改引擎核心。关键词策略模式、候选人、自定义 Behavior5会签 / 或签多人审批时走多实例。会签要按比例或全部通过才往下走或签一人通过即可还有依次审批。这些在用户任务的审批方式配置里体现运行时由自定义多实例 / UserTask Behavior 配合完成条件控制。审批方式枚举方式说明RANDOM随机挑选一人审批RATIO多人会签按通过比例ANY多人或签一人通过或拒绝SEQUENTIAL依次审批6业务单据事件回调引擎侧有流程实例、任务完成等监听器。流程结束或状态变更时发 Spring 的状态事件业务模块按流程定义 Key 实现 Listener把审批结果写回自己的表。这样业务只关心「结果」不依赖 Flowable API模块之间解耦。报废 Listener 示例逻辑监听流程 Keyoa_scrap_application用businessKey找到报废单 ID更新approvalStatus审批通过 → 自动执行报废审批拒绝/取消 → 恢复主档状态五、流程状态与业务状态一致性核心思路Flowable 管流程引擎状态业务表管单据状态用businessKey 事件回调做最终同步。双状态 关联字段维度Flowable 侧业务侧关联businessKey scrapIdprocessInstanceId审批状态流程变量PROCESS_STATUSapprovalStatus业务状态—applicationStatus一致性保障要点同一事务发起createProcessInstance和业务表更新放在同一个Transactional里终态驱动业务最终状态只跟流程实例终态APPROVE/REJECT/CANCEL绑定不跟单个 Task 绑定拒绝/取消补偿驳回时业务还原为 draft并恢复关联数据如状态防重复发起已有processInstanceId且非 reject/cancel 时不允许再发起中间进度查 Flowable列表页显示「谁在审」查 Task 表/API不靠业务表猜流程实例状态枚举状态值说明NOT_START-1未开始RUNNING1审批中APPROVE2审批通过REJECT3审批不通过CANCEL4已取消关键中间节点审批不会改业务终态只有流程结束processProcessInstanceCompleted才发 Spring 事件回写业务。六、单人审批 vs 审批组两个维度不要混为一谈维度配置项作用找谁审候选人策略角色 / 部门负责人 / 指定用户 /用户组等怎么审审批方式随机一人 / 会签 / 或签 / 依次审批单人审批候选人策略指定用户、部门负责人、角色等审批方式随机挑选一人审批RANDOM实现从候选人里随机选 1 个作为 assignee责任到人审批组用户组候选人策略用户组USER_GROUP展开组内所有用户审批方式再决定组内怎么审审批方式行为随机一人组里随机抽 1 人审或签组里任意 1 人通过即可会签按比例组里多人都要批达到比例才通过依次审批组里按顺序一个一个批七、网关分流指定人员直批 vs 审批组场景同一个流程通过排他网关分流指定人员→ 单人快速审批或轻量审批其他人→ 必须走审批组用户组 或签/会签流程模型发起 ↓ [排他网关directApprove ?] ├─ true → 指定人员通道单人节点 └─ false → 审批组通道用户组 或签/会签 ↓ 结束 → Listener 回写业务状态实现步骤1. 发起时计算变量业务代码MapString,ObjectvariablesnewHashMap();booleandirectApproveisDirectApprover(userId);// 白名单/角色/岗位规则variables.put(directApprove,directApprove);createReqDTO.setProcessDefinitionKey(PROCESS_KEY);createReqDTO.setBusinessKey(String.valueOf(scrapId));createReqDTO.setVariables(variables);processInstanceApi.createProcessInstance(userId,createReqDTO);2. 设计器配置网关分支 A 条件${directApprove true}→ 单人审批节点分支 B 条件默认分支 → 用户组 或签/会签3. Listener 不用改无论走哪条分支流程结束时都是同一个 End 事件业务 Listener 只监听终态。两种「直接通过」选择方式适用审计自动通过Service Task指定人员完全免审弱单人快速审批节点指定人员仍需点一次通过强推荐注意事项网关判断的是发起时就能确定的变量变量必须在发起时传入否则走默认分支指定人员分支建议仍保留一个审批节点避免完全无审八、常见追问速答面试官问你怎么回Activiti 和 Flowable 区别同源演进Activiti 偏社区老牌Flowable 在 Activiti 基础上持续演进。芋道用的是 FlowableAPI 和 BPMN 概念基本通用。表单怎么做的两种动态表单JSON 配置存扩展表和业务自定义表单业务自己存数据流程只走审批。和业务怎么解耦API 发起 businessKey 状态事件回调业务不直接依赖引擎表。多租户部署带 tenantId事件回调时按租户上下文执行。退回 vs 拒绝退回回到前面节点流程还在跑拒绝结束流程并触发终态事件。中间节点会改业务状态吗不会。只有流程终态通过/拒绝/取消才回写业务表。你具体做过什么报废/采购/计量/折旧等单据接入 BPM建流程模型、配审批人、业务发起、Listener 回写状态、联调通过拒绝退回。九、一分钟压缩版紧张时用芋道 BPM 基于 Flowable。定义发布走 Repository 部署业务用统一 API 按流程 Key 发起businessKey 绑单据审批封装 TaskService审批人用策略模式计算结束用 Spring 事件按流程 Key 回调业务改状态。我主要是把系统里的报废、采购、计量、折旧等业务按这套方式接进去并完成联调。十、容易踩坑的点问题说明中间节点改业务状态不要每个 Task complete 都改业务表只在流程终态改退回 vs 拒绝退回回到前面节点拒绝结束流程并触发终态事件用户组 随机一人组里多人但只随机 1 人审不是「组里所有人都能看到待办」用户组 或签组里每人都有待办任意一人通过即可分支条件变量发起时必须传入否则网关走默认分支防重复发起已有 processInstanceId 且非 reject/cancel 时不允许再发起十一、关键类名补充用不要一上来背能力关键类跨模块 APIBpmProcessInstanceApi状态事件BpmProcessInstanceStatusEvent业务 ListenerBpmProcessInstanceStatusEventListener审批人策略BpmTaskCandidateStrategy自定义 BehaviorBpmUserTaskActivityBehavior审批方式BpmUserTaskApproveMethodEnum流程状态BpmProcessInstanceStatusEnum十二、分布式场景状态同步与审批状态处理1. 三层状态模型先建立全局认识层级存储位置字段/变量谁维护生命周期流程实例状态FlowableACT_RU_VARIABLEPROCESS_STATUSBPM 模块流程开始到结束任务状态FlowableACT_RU_VARIABLETask LocalTASK_STATUS、审批意见BPM 模块单个 Task业务单据状态业务表approvalStatus、applicationStatus业务模块单据全生命周期原则Flowable 表是流程引擎的唯一真相源业务表是业务系统的唯一真相源两者通过businessKeyprocessInstanceId关联终态时对齐2. 单体 vs 分布式回调方式差异单体芋道默认Flowable 引擎 → Spring ApplicationEvent → 业务 Listener同 JVM优点简单、无网络开销、天然事务内缺点不能跨服务Listener 必须在同一进程分布式微服务Flowable/BPM 服务 → MQRocketMQ/Kafka→ 采购等业务服务消费Spring Event 改为MQ 消息消息体{ processDefinitionKey, businessKey, status, tenantId, processInstanceId }消费端幂等处理 按 businessKey 更新业务状态面试话术单体里用 Spring Event 做流程终态回调如果拆成微服务会把状态变更事件发到 MQ业务服务订阅后幂等更新单据状态保证跨服务最终一致。3. 发起流程时的分布式一致性问题业务落库和发起流程是两个操作分布式下可能业务单创建成功流程发起失败流程发起成功业务单更新 processInstanceId 失败方案方案 A本地事务同库同服务推荐Transactional(rollbackForException.class)publicStringstartScrapProcess(LonguserId,LongscrapId){// 1. 校验 防重复// 2. 调 BPM API 发起流程StringprocessInstanceIdprocessInstanceApi.createProcessInstance(...);// 3. 更新业务表 processInstanceId approvalStatusscrapApplicationMapper.updateById(...);returnprocessInstanceId;}业务模块和 BPM 模块共用数据库 → 同一事务要么全成功要么全回滚。方案 B先落库再发起 补偿跨服务1. 业务单状态 「待发起」 2. 调 BPM 服务发起流程 3. 成功 → 更新 processInstanceId 「审批中」 4. 失败 → 保持「待发起」定时任务/人工重试方案 CTCC / Saga大项目Try预占业务单锁定不可编辑Confirm发起流程成功改审批中Cancel发起失败释放锁定方案 DOutbox 模式高可靠1. 同一事务写业务单 写 outbox 消息表 2. 异步 Job 读 outbox → 调 BPM 发起流程 3. 成功后更新 processInstanceId标记 outbox 已处理4. 审批状态保存各层怎么存流程实例级PROCESS_STATUS存在 Flowable 流程变量里值RUNNING(1) / APPROVE(2) / REJECT(3) / CANCEL(4)发起时设为 RUNNING拒绝/取消时主动 setVariable正常结束时若还是 RUNNING → 自动改 APPROVE任务级TASK_STATUS存在 Task Local Variable每次 approve/reject/return 时写入用于审批详情页展示每个节点的审批结果不影响业务表仅供 BPM 模块查询业务表级approvalStatus发起时设为 RUNNING审批中终态回调时Listener 更新为 APPROVE / REJECT / CANCEL配合 applicationStatus 做业务语义draft / submitted / approved报废实际代码逻辑发起 → approvalStatusRUNNING, applicationStatussubmitted 通过 → approvalStatusAPPROVE, applicationStatusapproved, 自动执行报废 拒绝 → approvalStatusREJECT, applicationStatusdraft, 恢复状态5. 终态回调的分布式可靠性问题流程结束了但业务服务没收到 / 收到了但处理失败 → 状态不一致。解决思路手段说明至少一次投递MQ 确认机制消费失败重试幂等消费用businessKey status做去重已处理则跳过状态机校验只有当前是 RUNNING 才允许改为 APPROVE/REJECT补偿 Job定时扫描「审批中但流程已结束」的单据主动对齐对账任务比对 FlowableACT_HI_PROCINST与业务表状态幂等更新示例publicvoidupdateScrapApprovalStatus(LongscrapId,IntegerapprovalStatus){ScrapApplicationDOexistingscrapApplicationMapper.selectById(scrapId);// 已是终态跳过幂等if(BpmProcessInstanceStatusEnum.isProcessEndStatus(Integer.parseInt(existing.getApprovalStatus()))){return;}// 正常更新...}6. 并发审批场景或签两人同时点通过Flowable TaskService.complete 内部有乐观锁第一个 complete 成功 → 流程往下走其他 Task 被删除第二个 complete → 抛异常「任务不存在」业务侧无需额外处理重复发起流程业务层校验已有 processInstanceId 且非 reject/cancel → 拒绝分布式下加Redis 分布式锁lock:scrap:start:{scrapId}或数据库唯一索引process_instance_id非空时不允许再发起并发改业务单 发起流程业务表加version乐观锁或状态机只有 draft 状态才允许发起7. Flowable 集群部署注意点点说明共用数据库所有 BPM 节点连同一个 Flowable 库引擎状态天然一致Job Executor异步 Job / 定时器由 Flowable 内置锁机制ACT_RU_JOB.LOCK_*保证集群不重复执行不要本地缓存流程定义定义变更后需刷新或走 Repository 查询Authentication 传递多节点下通过 Filter 把当前用户写入 Flowable Authentication流程实例 ID芋道用 Redis 生成自定义流程 IDBpmProcessIdRedisDAO集群安全8. 跨服务查询「当前谁在审」分布式下业务服务不直接查 Flowable 表有两种方式调 BPM 服务 API传入 processInstanceId返回当前待办节点和审批人BPM 服务推事件每到一个新节点发 MQ 通知业务服务更新「当前审批人」字段可选非必须推荐列表页「审批中」只显示业务状态点详情时调 BPM API 查实时进度。9. 分布式事务选型对比面试常问方案适用优点缺点本地事务单体 / 同库模块简单可靠不能跨库跨服务最终一致 补偿微服务常规方案实现简单有短暂不一致窗口Outbox高可靠消息不丢消息多一张表 JobTCC金融级强一致实现复杂需改造业务Seata AT快速接入对业务侵入小性能开销Flowable 不一定兼容推荐答法工作流场景更适合最终一致性。流程引擎自身有事务保障业务侧通过终态事件 幂等 补偿 Job 对齐状态而不是强绑分布式事务。10. 补偿与对账机制补偿 Job建议了解定时任务如每 5 分钟1. 查业务表 approvalStatus RUNNING 且 createTime 30 分钟 2. 调 BPM 服务查对应 processInstanceId 是否已结束 3. 已结束 → 补发状态更新 4. 不存在 → 标记异常人工介入对账SELECT b.id, b.approval_status, h.END_TIME_, h.DELETE_REASON_ FROM scrap_application b LEFT JOIN ACT_HI_PROCINST h ON b.process_instance_id h.PROC_INST_ID_ WHERE b.approval_status 1 AND h.END_TIME_ IS NOT NULL → 这些就是「业务还在审批中但流程已结束」的异常单11. 分布式场景面试口述1 分钟流程状态在 Flowable 的 ACT 表里业务状态在业务表里通过 businessKey 关联。单体下用 Spring Event 做终态回调发起和落库放同一事务。如果拆微服务状态事件改走 MQ消费端做幂等更新并用补偿 Job 对账。审批中不会改业务终态只在流程结束通过/拒绝/取消时对齐。或签并发 complete 由 Flowable 乐观锁保证重复发起靠业务校验加 Redis 锁。整体思路是最终一致而不是强绑分布式事务。12. 分布式相关追问速答面试官问你怎么回Spring Event 能跨服务吗不能只在同一 JVM。微服务需改 MQ。流程成功但业务没更新怎么办补偿 Job 扫描 对账 幂等重试。需要 Seata 吗一般不需要工作流适合最终一致 补偿。或签两人同时批Flowable 内部乐观锁第二个会失败业务无感。怎么防重复发起业务校验 processInstanceId Redis 锁 状态机。Flowable 集群怎么部署多节点共用 Flowable 库Job Executor 自带锁。审批状态存几处三处流程变量 PROCESS_STATUS、Task Local、业务表 approvalStatus。中间节点要同步业务吗一般不要只同步终态除非业务强需求「当前审批人」。

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

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

免费获取报价