核心是用统一MessageSender接口抽象发送行为,文本、图片、语音等各类型实现类专注自身逻辑,通过type路由调用,新增类型只需添加实现类并注册,支持无状态并发与装饰器扩展。

核心是用统一接口抽象发送行为,让文本、图片、语音等消息类型各自实现具体逻辑,调用方只面向接口编程,不关心背后是哪种消息。
定义通用消息发送接口
声明一个 MessageSender 接口,包含 send(NoticeMessage msg) 方法。NoticeMessage 是泛化消息实体,含 type(如 "text"、"image")、receiver、content、extra 等通用字段。返回统一的 SendResult,封装 success、code、message、rawResponse 等信息。接口里不出现任何厂商参数(如阿里云 SignName 或腾讯云 SmsSdkAppId),这些细节全由实现类内部处理。
各消息类型实现自己的发送器
每种消息对应一个实现类:
- TextMessageSender:把 content 当纯文本,调用短信或站内信 SDK
- ImageMessageSender:先上传图片到 CDN,再拼装带 URL 的富媒体消息体,走 IM 通道发送
- VoiceMessageSender:校验音频格式与大小,生成播放链接和时长元数据,封装为语音消息结构
所有实现类都只专注“这一种消息怎么发”,不耦合其他类型逻辑。
立即学习“Java免费学习笔记(深入)”;
运行时按消息类型自动路由
不写 if-else 判断 msg.getType(),而是用策略映射表或 Spring Bean 名称匹配:
- 初始化时将各 Sender 实现注册进 Map<String, MessageSender>,key 为 msgType(如 "text" → TextMessageSender)
- 发送时根据 NoticeMessage.type 查出对应 Sender,直接调用 send() 方法
- 新增类型(如 “文件消息” 或 “位置消息”)只需加一个实现类 + 注册到 map,主流程完全不动
保障并发与状态隔离
即时通讯常面临批量消息并发发送:
- 每个 Sender 实例保持无状态,或仅持自身所需的配置(如 token、超时时间),不共享连接或缓存
- 异步回调统一用 msgId 作为上下文 key,避免 A 消息的回调误更新 B 消息的状态
- 失败重试、限流熔断等横切逻辑抽成装饰器(如 RetryMessageSender),套在原始 Sender 外层,不影响类型扩展


















