代购系统的可扩展通知机制:从硬编码到观察者模式,借鉴taocarts的事件总线

简介: 本文分享代购系统通知模块的演进之路:从硬编码通知到基于Spring事件总线的解耦设计。通过抽象订单事件、注解式监听器、异步执行与Webhook动态订阅,实现高可扩展、易维护的通知体系,彻底告别“改一处崩全局”的困境。

三年前我写第一个代购系统的时候,所有的邮件、短信、站内信都直接写在业务逻辑里。后来运营要增加钉钉机器人通知,我改代码改到吐。再后来要加 Webhook 推送给第三方仓库系统,更是痛苦。直到我研究了 taocarts 的事件总线设计,用观察者模式彻底重构了通知模块,才终于解脱。

一、代购系统有哪些通知需求?
一套完整的反向海淘平台需要通知的场景非常多:

用户下单后,通知采购员(钉钉/飞书)

淘宝卖家发货后,通知用户(邮件 + 站内信)

包裹到达代购转运仓,提醒用户合箱(短信)

国际集运出库后,推送轨迹给用户的微信

财务需要订阅所有订单状态变更(Webhook 到内部对账系统)

如果用 if (status == 3) sendEmail() 这种方式,三个月后代码就没人敢动了。

二、taocarts的事件驱动设计
taocarts 实现了一个轻量级的 EventDispatcher,支持多个监听器订阅同一个事件。我把它翻译成了 Java 版本(我们主栈是 Spring):

首先定义一个事件抽象类:
```public abstract class OrderEvent extends ApplicationEvent {
private final Long orderId;
private final OrderState newState;

public OrderEvent(Object source, Long orderId, OrderState newState) {
    super(source);
    this.orderId = orderId;
    this.newState = newState;
}
// getters

}


具体事件:OrderShippedEvent, ParcelArrivedEvent, ConsolidationCompletedEvent 等。

然后定义监听器接口(注解式):
```@Component
public class EmailNotifier {
    @EventListener
    public void handleOrderShipped(OrderShippedEvent event) {
        Order order = orderService.getById(event.getOrderId());
        String subject = "您的订单已从淘宝发货";
        String body = buildEmailContent(order);
        emailClient.send(order.getUserEmail(), subject, body);
    }
}

钉钉通知:

public class DingTalkNotifier {
    @EventListener
    public void handleParcelArrived(ParcelArrivedEvent event) {
        String message = String.format("包裹 %s 已到达集运仓,请及时处理", event.getTrackingNo());
        dingTalkClient.sendToGroup(message);
    }
}

Webhook 给第三方系统(比如代购集运的WMS):

public class WebhookNotifier {
    @EventListener
    public void onOrderStatusChanged(OrderStatusChangedEvent event) {
        // 遍历所有已注册的webhook url
        List<String> urls = webhookRepo.findByEventType(event.getNewState().name());
        for (String url : urls) {
            restTemplate.postForEntity(url, event, Void.class);
        }
    }
}

三、异步化防止影响主流程
默认情况下 Spring 的 @EventListener 是同步的,如果钉钉接口超时,用户下单也会慢。我们改用 @Async:

@EnableAsync
public class AsyncConfig {
    @Bean(name = "notificationExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setThreadNamePrefix("notify-");
        executor.initialize();
        return executor;
    }
}

@Component
public class DingTalkNotifier {
    @Async("notificationExecutor")
    @EventListener
    public void handleParcelArrived(ParcelArrivedEvent event) {
        // 异步发送,不阻塞主流程
    }
}

四、与taocarts的区别
taocarts 的事件系统没有提供异步选项,所有的监听器顺序执行。如果某个监听器抛出异常,后续监听器就不会执行。我在生产环境遇到过因为邮件服务器超时导致整个订单保存失败的问题。所以后来我们做了两个改进:

所有通知类监听器都用 @Async

关键业务监听器(比如库存扣减)用同步,并且放在事务提交后执行(@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT))

五、扩展:让用户自己配置 Webhook
跨境独立站的商家经常需要把自己的系统和我们代购系统对接。我们开发了一个 Webhook 管理界面,允许商家填写 URL 和订阅的事件类型(比如 order.paid, order.shipped)。

存储结构:
``CREATE TABLEwebhook_subscriptions(idint,merchant_idint,event_namevarchar(64),target_urlvarchar(255),secret` varchar(64) -- 用于签名验证
);


触发时用 HMAC-SHA256 签名:
```String payload = objectMapper.writeValueAsString(event);
String signature = HmacUtils.hmacSha256Hex(secret, payload);
httpHeaders.set("X-Signature", signature);

这套机制上线后,有三家海外物流公司通过 Webhook 接入了我们的国际集运轨迹推送,完全不需要我们改代码。

六、总结
观察者模式 + 事件总线 是代购源码必备的扩展能力。taocarts 给了我们一个很好的起点,但生产环境还需要考虑异步、重试、死信队列。我个人建议,如果你的系统监听器超过 5 个,就赶紧重构,否则后面全是坑。

相关文章
|
2月前
|
人工智能 Linux API
hermes agent 部署实战:环境准备、模型接入与网关配置4.0版
Hermes Agent 是 Nous Research 于 2026 年开源的 MIT 协议 AI 智能体框架(Python 实现,v0.14.0)。采用任务驱动架构,支持技能自动沉淀、持久化记忆、原生多工具链(搜索/终端/文件/浏览器)、并行任务处理及跨平台部署(Linux/macOS/Windows+WSL2),开箱即用。
|
2月前
|
人工智能 安全 JavaScript
Win11 用户狂喜 OpenClaw 一键部署,办公效率直接翻倍
OpenClaw 2.7.5 是面向Windows的本地化AI智能体工具,支持一键部署、离线运行与数据零上传。集成400+大模型及系统级功能(文件/浏览器/键鼠自动化),内置全环境依赖,无需配置。适配Win10/11,要求4GB内存+10GB磁盘,部署后即可快速启用私有AI助手。
|
2月前
|
机器学习/深度学习 监控 安全
人群计数行人检测数据集分享(适用于YOLO系列深度学习检测任务)
本数据集含9000张行人图像(7200训练+1800验证),覆盖街道、商场、地铁等多场景,已精准标注YOLO格式,支持YOLOv8/RT-DETR等框架直接训练,适用于人群计数、智慧安防与流量分析。
324 0
|
2月前
|
缓存 并行计算 测试技术
如何在单张 RTX 3090 上让 Qwen3.5-27B token 生成速度提升 6 倍
本文系 trycua 团队的工程实践分享,Cua 是由该团队打造的一个面向 macOS 设计的开源 AI Agent 框架。下文采用第一视角来讲述他们在 RTX 3090 上的提速实践。
506 3
|
2月前
|
存储 Web App开发 机器学习/深度学习
Claude 官方的 Agent Memory 管理实践:为什么用文件系统保存记忆?
现在 Claude Managed Agents(可在 Claude Platform 上使用)有了记忆(memory)能力。这些记忆以文件的形式保存下来,供单个 Agent 或者多个 Agent 在不同会话间继续访问和使用。简单来说,Agent 不再“只活在当下”,能从过去执行任务的经验中学习。用户也可以通过 API 导出记忆,方便后续查看或使用。
257 0
Claude 官方的 Agent Memory 管理实践:为什么用文件系统保存记忆?
|
2月前
|
人工智能 安全 开发者
把大佬的方法装进你的 AI 技能包!假期值得试试的 6 个有趣 Skill
有开发者把马斯克、巴菲特、大神 Karpathy,还有一些知名博主的工作方法,做成了可以直接在终端(比如 Claude Code)里调用的 Skill。
361 0
把大佬的方法装进你的 AI 技能包!假期值得试试的 6 个有趣 Skill
|
2月前
|
人工智能 Oracle 机器人
推理 → 行动 → 观察:用 LangChain + Python 实现一个智能体循环
智能体循环(Agentic Loop)突破单次问答局限,通过“推理→行动→观察”迭代闭环,让AI能自主分解任务、调用工具、持续优化直至目标完成,是构建真正自动化智能体的核心架构。
397 9
推理 → 行动 → 观察:用 LangChain + Python 实现一个智能体循环
|
2月前
|
测试技术 定位技术 开发工具
海外 APP 开发与上线
APP出海远不止翻译界面!需攻克四大关键战役:①云架构迁移+真本地化(UI/UX、登录方式、时区货币);②严守GDPR/CCPA等隐私合规,通过苹果Privacy Manifest与谷歌Data Safety审核;③接入IAP(苹果/谷歌)、Stripe/PayPal或AdMob等海外支付与广告体系;④完成ASO本地化、灰度上线及商店资质准备。代码须彻底“去国内SDK化”。
|
2月前
|
弹性计算 前端开发 Ubuntu
阿里云服务器ECS的租用教程和简单的前端页面部署
本文详解阿里云学生福利领取(含300元卡券)及ECS轻量服务器选购与部署全流程:涵盖学生机免费申领、配置选型建议(Ubuntu/CentOS/Windows)、安全组设置、Nginx安装、网页部署及Xshell远程连接等实操步骤,新手友好。
388 8
|
2月前
|
人工智能 运维 网络安全
我这半年实际使用过的 4 款 SSH 工具体验分享
本文精选4款主流SSH工具:轻量稳定的PuTTY、Windows全能神器MobaXterm、跨平台云同步的Termius,以及AI驱动的智能终端Aeroshell,覆盖从经典运维到AI辅助新场景,助开发者与运维人员高效管理服务器。(239字)
995 1
我这半年实际使用过的 4 款 SSH 工具体验分享