SseEmitter
是 Spring Framework 提供的一个类,用于支持服务器发送事件(Server-Sent Events,SSE)。SSE 是一种基于 HTTP 的协议,允许服务器向客户端推送实时数据,而不需要客户端不断地轮询服务器。SSE 特别适用于需要实时更新数据的场景,例如实时通知、实时数据流等。
SseEmitter 的主要特点:
- 单向通信:SSE 是单向的,服务器可以向客户端推送数据,但客户端不能向服务器发送数据。
- 基于 HTTP:SSE 使用标准的 HTTP 协议,因此不需要额外的协议支持。
- 自动重连:如果连接中断,客户端会自动尝试重新连接服务器。
- 事件流格式:SSE 使用简单的文本格式来传输数据,每条消息以
data:
开头,并以两个换行符\n\n
结束。
SseEmitter 的基本用法:
- 创建 SseEmitter 实例:在控制器中创建一个
SseEmitter
实例,并将其返回给客户端。 - 发送事件:通过
SseEmitter
实例的send
方法向客户端发送事件。 - 处理连接关闭:通过
SseEmitter
的onCompletion
和onTimeout
方法处理连接关闭或超时的情况。
示例代码:
一个简单的 Spring Boot 示例
1. 创建一个控制器类:
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@RestController
public class SseController {
private final ExecutorService nonBlockingService = Executors.newCachedThreadPool();
@GetMapping("/sse")
public SseEmitter handleSse() {
SseEmitter emitter = new SseEmitter();
nonBlockingService.execute(() -> {
try {
for (int i = 0; i < 10; i++) {
SseEmitter.SseEventBuilder event = SseEmitter.event()
.data("SSE event - " + i)
.id(String.valueOf(i))
.name("sse event")
.reconnectTime(10_000L);
emitter.send(event);
Thread.sleep(1000); // 模拟延迟
}
emitter.complete(); // 完成发送
} catch (IOException | InterruptedException e) {
emitter.completeWithError(e);
}
});
return emitter;
}
}
2. 客户端代码(Js):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSE Example</title>
</head>
<body>
<h1>Server-Sent Events Example</h1>
<ul id="eventList"></ul>
<script>
const eventSource = new EventSource('/sse');
const eventList = document.getElementById('eventList');
eventSource.onmessage = function(event) {
const newElement = document.createElement("li");
newElement.textContent = "Event: " + event.data;
eventList.appendChild(newElement);
};
eventSource.onerror = function() {
console.error("EventSource failed.");
};
</script>
</body>
</html>
解释:
-
服务器端:
SseController
类中的handleSse
方法创建了一个SseEmitter
实例,并将其返回给客户端。- 使用
ExecutorService
来异步发送事件,避免阻塞主线程。 - 在循环中,每隔 1 秒发送一个事件,共发送 10 个事件。
- 事件包含数据、ID、名称和重连时间。
-
客户端:
- 使用
EventSource
API 连接到服务器端的/sse
端点。 - 每当接收到一个事件时,
onmessage
回调函数会被触发,并将事件数据添加到页面上的列表中。
- 使用
注意事项:
- 超时设置:
SseEmitter
默认的超时时间是 30 秒,可以通过SseEmitter
的构造函数设置自定义的超时时间。 - 线程安全:在多线程环境中使用
SseEmitter
时,需要注意线程安全问题。 - 错误处理:在实际应用中,应该处理连接中断、超时等异常情况。