SSE、EventSource理解与实践
本文最后更新于 2025-03-30,文章超过7天没更新,应该是已完结了~
1. 什么是 EventSource
?
EventSource
是一种服务器发送事件(Server-Sent Events, SSE)的工具或接口,常用于从服务器向客户端推送实时更新数据。这种机制适用于需要轻量级、单向通信的场景。
2. 基础概念
服务器发送事件(SSE):
是一种HTTP 长连接机制,允许服务器通过持续的连接推送数据给客户端。
使用了简单的 HTTP 协议而非 WebSocket,所以无需复杂的握手或协议切换。
特点:
单向通信:服务器推送数据,客户端接收,不能反向发送数据。
自动重连:当连接断开时,浏览器或客户端会自动尝试重新连接。
轻量级:相比 WebSocket 更加轻量,适用于事件更新、通知等。
适用场景:
实时数据更新:股票行情、天气更新等。
通知推送:系统通知、消息提醒。
流式输出:日志实时显示、大文件下载进度等。
2. EventSource 工具的作用
在 Java 中,EventSource
是一个接口,它定义了 SSE 的核心功能,负责管理与服务器的事件流通信。
主要功能:
建立连接: 使用底层的 HTTP 客户端发起长连接请求(如
OkHttpClient
)。监听事件: 通过
EventSourceListener
接口接收服务端推送的事件数据。管理连接生命周期: 支持手动关闭连接或在发生错误时进行处理。
3. EventSource 的核心接口
(1)EventSource
EventSource
是核心接口,定义了事件流的基本操作。
public interface EventSource {
/**
* 获取当前事件源的请求
*/
Request request();
/**
* 取消当前事件流,关闭连接
*/
void cancel();
/**
* 工厂接口,用于创建事件源
*/
interface Factory {
/**
* 创建新的事件源
* @param request HTTP 请求
* @param listener 事件监听器
* @return 事件源
*/
EventSource newEventSource(Request request, EventSourceListener listener);
}
}
(2)EventSourceListener
EventSourceListener
是事件流的监听接口,处理服务端推送的事件数据和连接状态。
public interface EventSourceListener {
/**
* 接收到事件数据
*/
void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data);
/**
* 连接关闭时调用
*/
void onClosed(EventSource eventSource);
/**
* 连接失败或发生错误时调用
*/
void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response);
}
(3)EventSources 工厂
EventSources
是一个工具类,提供创建 EventSource.Factory
的方法。
public final class EventSources {
public static EventSource.Factory createFactory(OkHttpClient client) {
return new EventSource.Factory() {
@Override
public EventSource newEventSource(Request request, EventSourceListener listener) {
RealEventSource realEventSource = new RealEventSource(request, listener);
realEventSource.connect(client);
return realEventSource;
}
};
}
}
为什么使用相似的名字?
使用相似的名字是为了表达两者之间的关联性,同时保持语义清晰。
语义上的一致性:
EventSource
是核心接口,表示一个事件流。EventSources
是工具类,用于操作EventSource
或创建工厂。这种命名方式直观地传达了
EventSources
是围绕EventSource
的辅助类。
单一职责原则:
EventSource
专注于定义事件流的行为。EventSources
专注于提供与事件流相关的辅助方法。两者职责分明但紧密相关,使用类似名字是合理的。
命名惯例: 在 Java 中,类似的命名方式很常见:
Collections
(工具类) vsCollection
(接口)。Executors
(工具类) vsExecutor
(接口)。Streams
(工具类) vsStream
(接口)。
4. EventSource 的用法
(1)基础用法示例
以下是一个完整的使用示例,展示如何创建和使用 EventSource
:
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import java.util.concurrent.TimeUnit;
public class EventSourceExample {
public static void main(String[] args) {
// 创建 OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS) // SSE 长连接无超时
.build();
// 创建 EventSource 工厂
EventSource.Factory factory = EventSources.createFactory(client);
// 构建请求
Request request = new Request.Builder()
.url("https://example.com/sse") // 服务器 SSE 地址
.build();
// 创建事件源
factory.newEventSource(request, new EventSourceListener() {
@Override
public void onEvent(EventSource eventSource, String id, String type, String data) {
System.out.println("接收到事件:类型 = " + type + ",数据 = " + data);
}
@Override
public void onClosed(EventSource eventSource) {
System.out.println("事件源已关闭");
}
@Override
public void onFailure(EventSource eventSource, Throwable t, Response response) {
System.err.println("事件源错误:" + t.getMessage());
}
});
}
}
5. 核心概念和机制
(1)Server-Sent Events (SSE)
协议: 基于 HTTP,使用
text/event-stream
内容类型。
格式: 服务端推送的事件以纯文本方式发送,格式如下:
id: 1
event: message
data: {"message": "Hello World"}
(2)EventSource 工厂模式
使用
EventSource.Factory
隔离具体实现。提供统一的创建方式,便于扩展和管理。
(3)连接生命周期
事件源在以下情况下终止连接:
服务端主动关闭连接。
客户端调用
EventSource.cancel()
。发生网络异常或超时。
(4)自动重连
如果需要自动重连,可以在
onFailure
回调中重新调用newEventSource
。
6. 与 WebSocket 的对比
7. 优势与局限
优势:
轻量化:简单易用,基于 HTTP。
自动重连:无需手动管理断线重连。
浏览器支持好:大多数现代浏览器原生支持。
节省资源:只需要单向通信时,比 WebSocket 更省资源。
局限:
单向通信:只能服务器向客户端推送数据。
功能有限:不支持二进制数据传输,只能发送文本数据。
跨域限制:SSE 需要处理跨域问题。
- 感谢你赐予我前进的力量