当前位置: 首页 > news >正文

别再只用定时器了!Flowable事件子流程结合消息事件的3个高级玩法

Flowable事件子流程结合消息事件的3个高阶实践

当我们需要在业务流程中实现异步通知、跨系统解耦或复杂事件驱动逻辑时,传统的定时器和顺序流往往显得力不从心。Flowable的事件子流程配合消息事件机制,为这类场景提供了优雅的解决方案。本文将分享三种实际项目中验证过的高级用法,帮助您构建更灵活、更健壮的流程系统。

1. 非中断式邮件通知子流程

审批流程中最常见的需求之一是在关键节点自动发送通知邮件。传统做法是在主流程中直接添加邮件任务,但这会导致流程与通知逻辑强耦合。利用消息事件触发的事件子流程可以完美解决这个问题。

假设我们有一个采购审批流程,当审批通过时需要自动发送邮件通知申请人。以下是实现步骤:

  1. 在主流程的审批通过节点后添加一个消息抛出事件
<sequenceFlow id="flowApprove" sourceRef="approveTask" targetRef="approvedMessage" /> <intermediateThrowEvent id="approvedMessage"> <messageEventDefinition messageRef="approvalMsg" /> </intermediateThrowEvent>
  1. 创建事件子流程并定义消息开始事件:
<subProcess id="emailSubProcess" triggeredByEvent="true"> <startEvent id="messageStart"> <messageEventDefinition messageRef="approvalMsg" /> </startEvent> <serviceTask id="sendEmailTask" flowable:type="mail"> <extensionElements> <flowable:field name="to"> <flowable:string>${applicantEmail}</flowable:string> </flowable:field> <flowable:field name="subject"> <flowable:string>您的采购申请已批准</flowable:string> </flowable:field> </extensionElements> </serviceTask> <sequenceFlow sourceRef="messageStart" targetRef="sendEmailTask" /> <endEvent id="emailEnd" /> <sequenceFlow sourceRef="sendEmailTask" targetRef="emailEnd" /> </subProcess>

这种设计有几个显著优势:

  • 解耦:邮件逻辑独立于主流程,修改通知方式不影响主流程
  • 异步性:邮件发送不会阻塞主流程执行
  • 可重用:同一消息可以触发多个并行子流程

实际项目中我们发现,当邮件服务暂时不可用时,这种设计能自动重试,而不会影响主流程的后续操作。

2. 流程中工作流:等待外部系统回调

在集成第三方系统时,经常需要暂停流程等待外部回调。传统做法是使用接收任务(Receive Task),但这种方式难以处理超时和异常。消息事件子流程提供了更健壮的解决方案。

以订单支付流程为例,当需要等待支付网关回调时:

  1. 定义支付网关回调的消息事件:
<subProcess id="paymentCallbackProcess" triggeredByEvent="true"> <startEvent id="paymentStart"> <messageEventDefinition messageRef="paymentCallbackMsg" /> </startEvent> <serviceTask id="processPayment" flowable:expression="${paymentService.processCallback(execution)}" /> <boundaryEvent id="timeoutEvent" attachedToRef="processPayment"> <timerEventDefinition> <timeDuration>PT30M</timeDuration> </timerEventDefinition> </boundaryEvent> <endEvent id="paymentEnd" /> <sequenceFlow sourceRef="paymentStart" targetRef="processPayment" /> <sequenceFlow sourceRef="processPayment" targetRef="paymentEnd" /> </subProcess>
  1. 主流程中触发支付操作后,流程会暂停等待:
// 支付服务中触发回调 runtimeService.createMessageCorrelation("paymentCallbackMsg") .processInstanceId(processInstanceId) .setVariable("paymentStatus", "SUCCESS") .correlate();

关键设计要点:

  • 通过boundaryEvent设置30分钟超时
  • 外部系统通过REST API触发消息事件
  • 支付状态通过消息携带的变量传递
对比方案接收任务消息事件子流程
超时处理需要额外边界事件内置超时机制
异常处理单一可定义多种消息类型
可测试性困难易于模拟测试

3. 子流程内消息捕获 vs 事件子流程

虽然消息事件可以在常规子流程中使用,但与事件子流程有本质区别。通过一个用户注册的案例来说明两者的适用场景。

场景A:注册后的欢迎流程(使用常规子流程)

<subProcess id="welcomeSubProcess"> <startEvent id="welcomeStart" /> <intermediateCatchEvent id="waitForActivation"> <messageEventDefinition messageRef="activationMsg" /> </intermediateCatchEvent> <serviceTask id="sendWelcome" flowable:type="mail" /> <sequenceFlow sourceRef="welcomeStart" targetRef="waitForActivation" /> <sequenceFlow sourceRef="waitForActivation" targetRef="sendWelcome" /> </subProcess>

场景B:注册失败的重试流程(使用事件子流程)

<subProcess id="retrySubProcess" triggeredByEvent="true"> <startEvent id="retryStart"> <messageEventDefinition messageRef="retryMsg" /> </startEvent> <serviceTask id="retryRegistration" flowable:delegateExpression="${retryService}" /> <endEvent id="retryEnd" /> <sequenceFlow sourceRef="retryStart" targetRef="retryRegistration" /> <sequenceFlow sourceRef="retryRegistration" targetRef="retryEnd" /> </subProcess>

选择依据:

  • 常规子流程:当消息处理是业务流程的必经步骤时使用
  • 事件子流程:当消息处理是异常或可选路径时使用

性能考虑方面,事件子流程的消息订阅在流程启动时就建立,而常规子流程只在执行到捕获事件时才建立订阅。在高并发场景下,这会影响系统资源占用。

4. 高级模式:动态消息路由

对于更复杂的场景,我们可以结合消息事件和流程变量实现动态路由。例如在一个多租户的CRM系统中,不同客户需要触发不同的后续流程:

  1. 定义通用消息事件子流程:
<subProcess id="dynamicSubProcess" triggeredByEvent="true"> <startEvent id="dynamicStart"> <messageEventDefinition messageRef="dynamicMsg" /> </startEvent> <serviceTask id="dynamicTask" flowable:expression="${tenantService.getHandler(execution).process(execution)}" /> <endEvent id="dynamicEnd" /> <sequenceFlow sourceRef="dynamicStart" targetRef="dynamicTask" /> <sequenceFlow sourceRef="dynamicTask" targetRef="dynamicEnd" /> </subProcess>
  1. 通过消息属性实现路由:
Map<String, Object> variables = new HashMap<>(); variables.put("tenantId", "clientA"); variables.put("processType", "leadFollowUp"); runtimeService.createMessageCorrelation("dynamicMsg") .processInstanceId(processInstanceId) .setVariables(variables) .correlate();
  1. 租户服务根据变量选择处理器:
public class TenantService { public ProcessHandler getHandler(DelegateExecution execution) { String tenantId = (String) execution.getVariable("tenantId"); String processType = (String) execution.getVariable("processType"); // 返回特定租户和流程类型的处理器 return handlerRegistry.getHandler(tenantId, processType); } }

这种模式特别适合:

  • SaaS多租户应用
  • 需要后期扩展的业务流程
  • 不同客户有定制需求的场景

在最近的一个电商平台项目中,我们使用这种设计支持了17种不同的订单履约流程,而核心流程定义保持不变。当新增客户特定逻辑时,只需要实现新的处理器类,无需修改流程定义。

http://www.jsqmd.com/news/762008/

相关文章:

  • 如何快速配置游戏翻译插件:面向玩家的完整指南
  • PHP表单引擎必须支持的8种现代交互:文件分片上传、实时校验、多步向导、离线缓存…(附Vue+PHP混合渲染模板)
  • Humanfile:为AI编码助手划定边界,实现可控人机协作
  • 收藏必备!小白程序员轻松入门:N8n+Ollama+Qwen3打造企业级RAG知识库系统
  • AI代理决策优化:结构化辩论引擎Amogus的设计与实现
  • 别再只刷单色了!用STM32F4的SPI DMA功能,让你的ST7735S TFTLCD刷新速度飞起来
  • RLHI强化学习在智能对话系统中的应用与实践
  • 如何构建终极英雄联盟自动化工具集:基于LCU API的5大核心技术实现指南
  • Dify 2026边缘节点部署实录:从零编译→K3s轻量集群→毫秒级本地LLM响应,7步落地不踩坑
  • Streamlit组件样式改造指南:手把手教你定位st.button和st.dataframe的CSS类名
  • 2026 AI模型API代理网站亲测:五大优质平台大揭秘,谁能成为企业与开发者的心头好?
  • 嵌入式控制中的模糊逻辑应用与优化
  • 收藏!小白程序员必看:尽早认识大模型的价值,抓住时代机遇!
  • 保姆级教程:在Uniapp组件里成功调用抖音video-player播放短剧
  • LeetCode 283. 移动零
  • VCS覆盖率进阶:如何用-cm_cond参数精准控制条件覆盖率收集范围?
  • 仅限本周开放!PHP AI校验私有化部署终极套件(含Nginx+PHP-FPM+ONNX Runtime+Redis缓存预热一键脚本)
  • CompressO:免费开源的终极视频压缩解决方案,让你的大文件瞬间变小
  • 用快马ai十分钟复刻typora:打造你的在线实时markdown编辑器原型
  • 告别模拟器限制!在真机Android车机上调试多屏互动功能的完整流程与避坑指南
  • 别再死记硬背公式!用‘旋转矢量法’图解简谐运动,5分钟搞懂相位和初相位
  • Think3D框架:三维视觉语言模型的技术解析与应用
  • 超越基础回归:用SPSS时间序列功能优雅处理数据自相关(含差分法实战)
  • Pytorch图像去噪实战(四十):端到端OCR增强实战,用图像去噪模型提升文字识别准确率
  • CI/CD 是软件开发中的两个核心实践,合起来指代一套自动化的软件交付流程
  • 2026年开店选择财联支付靠谱吗?一文带你揭秘支付新选择
  • Dify工作流调试实战手册(附12个真实生产环境断点截图与trace ID追踪模板)
  • 2026年震撼发布!AI模型接口中转平台排行榜大揭秘,谁能脱颖而出?
  • 新手前端如何起步?用快马复刻idea官网来学习网页开发基础
  • 从Excel到Python:用Pandas的滚动窗口(rolling)做时间序列方差分析实战