sse 本身不支持多路复用,需通过应用层协议模拟多频道:服务端统一推送带 channel 字段或 event 类型的消息,客户端按类型过滤分发;推荐使用原生 event 字段实现语义化路由。

JavaScript 中的 SSE(Server-Sent Events)本身不支持原生多路复用或多频道订阅,它本质是单个 HTTP 长连接、单向(服务端→客户端)、单流传输。但可以通过应用层协议设计模拟“分频道”行为,核心思路是:**服务端统一推送带类型标识的消息,客户端按需过滤和分发**。
服务端统一发送带 channel 字段的消息
不要为每个频道建立独立 SSE 连接(会耗尽浏览器并发连接数,且无法复用)。改为服务端在一条 SSE 流中发送结构化消息,例如:
{
"channel": "notifications",
"data": {"id": 123, "text": "你有一条新消息"}
}
{
"channel": "stock-ticker",
"data": {"symbol": "AAPL", "price": 192.45}
}
服务端只需确保每条 event-stream 消息使用标准 SSE 格式(如 data: {...} 或自定义 event: + data:),并在 JSON 内容中嵌入 channel 字段用于路由。
客户端用 Map 管理多个频道监听器
创建一个 ChannelManager 类,内部用 Map 存储各频道对应的回调函数,收到原始消息后解析并派发:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
示例代码:
class ChannelManager {
constructor(url) {
this.eventSource = new EventSource(url);
this.handlers = new Map(); // channel → Array<function>
this.eventSource.onmessage = (e) => {
try {
const msg = JSON.parse(e.data);
const { channel, data } = msg;
const listeners = this.handlers.get(channel) || [];
listeners.forEach(cb => cb(data));
} catch (err) {
console.warn('Invalid SSE message:', e.data);
}
};
}
subscribe(channel, callback) {
if (!this.handlers.has(channel)) {
this.handlers.set(channel, []);
}
const list = this.handlers.get(channel);
list.push(callback);
return () => {
const idx = list.indexOf(callback);
if (idx > -1) list.splice(idx, 1);
};
}
}
// 使用
const cm = new ChannelManager('/api/events');
cm.subscribe('notifications', n => console.log('通知:', n));
cm.subscribe('stock-ticker', s => console.log('股价:', s));
</function>
可选:用 event 类型区分频道(兼容性更强)
SSE 原生支持 event: 字段,浏览器会将不同 event 名称的消息分发到对应 addEventListener(eventName, ...)。服务端可这样发:
event: notifications
data: {"id": 123, "text": "新消息"}
event: stock-ticker
data: {"symbol": "GOOGL", "price": 142.88}
客户端直接监听:
const es = new EventSource('/api/events');
es.addEventListener('notifications', e => {
const data = JSON.parse(e.data);
console.log('通知:', data);
});
es.addEventListener('stock-ticker', e => {
const data = JSON.parse(e.data);
console.log('行情:', data);
});
✅ 优点:无需手动解析 JSON 中的 channel 字段,语义清晰;❌ 缺点:event 名称不能含空格或特殊字符,动态频道名需提前约定或服务端预注册。
注意连接与错误处理
SSE 天然支持自动重连,但需合理配置:
- 服务端响应头加
Cache-Control: no-cache和Content-Type: text/event-stream - 避免在客户端频繁
close()+new EventSource(),应复用同一实例 - 监听
onerror并判断es.readyState === 0表示连接已断开且未自动重试(此时可手动恢复逻辑) - 敏感业务建议加消息 ID(
id:字段)和简单去重/断线续传逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










