Spring SseEmitter 全面解析与使用示例
- [Spring SseEmitter 全面解析与使用示例](#Spring SseEmitter 全面解析与使用示例)
-
-
- [一、SseEmitter 核心作用(一句话讲透)](#一、SseEmitter 核心作用(一句话讲透))
- 二、为什么要用它?(对比传统方式)
- 三、你这段代码的逻辑拆解(对应作用)
- 四、典型使用场景(对应你的代码)
- 五、关键特性补充
- 总结
-
Spring SseEmitter 全面解析与使用示例
你这段代码里用到的 SseEmitter 是 Spring 提供的服务端向客户端推送数据的核心工具,我用最通俗的方式给你讲清楚它的作用、核心价值和代码逻辑:
一、SseEmitter 核心作用(一句话讲透)
SseEmitter 是实现 SSE(Server-Sent Events,服务器发送事件) 的 Spring 封装类,本质是让服务端能主动、持续地向客户端(浏览器)推送数据 ,且是单通道的单向通信(服务端→客户端),不用客户端反复发请求(比如轮询)。
二、为什么要用它?(对比传统方式)
| 传统方式(轮询) | SseEmitter(SSE) |
|---|---|
| 客户端每隔几秒发一次请求问服务端"有没有新数据" | 客户端只发1次请求,服务端保持连接,有数据就主动推 |
| 频繁请求,浪费带宽和服务器资源 | 长连接+按需推送,资源消耗极低 |
| 实时性差(取决于轮询间隔) | 实时性极高(服务端有数据立刻推) |
三、你这段代码的逻辑拆解(对应作用)
java
@GetMapping("/sseEmitter")
public SseEmitter sseEmitterTest() {
// 1. 创建SseEmitter对象,设置超时时间60秒(超过60秒没交互就断开)
SseEmitter sseEmitter = new SseEmitter(60 * 1000L);
// 2. 开启虚拟线程(轻量),在后台持续推送数据
Executors.newVirtualThreadPerTaskExecutor().submit(() -> {
try {
// 3. 循环1000次,每500毫秒给客户端推一次数据("happy0"、"happy1"...)
for (int i = 0; i < 1000; i++) {
sseEmitter.send("happy" + i); // 核心:服务端主动推数据给客户端
Thread.sleep(500);
}
} catch (Exception e) {
// 4. 出错时标记连接异常结束
sseEmitter.completeWithError(e);
} finally {
// 5. 推送完成/出错后,主动关闭连接
sseEmitter.complete();
}
});
// 6. 返回SseEmitter,保持客户端和服务端的长连接
return sseEmitter;
}
四、典型使用场景(对应你的代码)
你的代码是"循环推送固定内容"的示例,实际开发中 SseEmitter 常用在:
-
实时消息通知:比如系统告警、订单状态变更、聊天消息;
-
进度条展示:比如文件上传/下载进度、任务执行进度;
-
实时数据刷新:比如股票行情、监控指标、日志实时输出;
-
流式返回:比如大模型回答的逐字输出(ChatGPT打字机效果)。
五、关键特性补充
-
单向通信:只能服务端推给客户端,客户端不能通过这个连接给服务端发数据(需要的话可以配合普通接口);
-
长连接:连接会保持到超时、推送完成或主动关闭;
-
兼容普通HTTP :基于HTTP协议,不用像WebSocket那样单独建连接,浏览器原生支持(
EventSource)。
总结
-
SseEmitter是 Spring 对 SSE 的封装,核心是服务端主动、持续向客户端推数据; -
相比轮询更高效、实时性更高,相比 WebSocket 更轻量(适合单向推送场景);
-
你的代码示例是典型用法:创建长连接→后台线程循环推送→完成/出错后关闭连接。