前端通信库fetch-event-source实现丰富的SSE
环境:SpringBoot3.4.0 + Vue3
1. 简介
SSE(Server-Sent Events)是一种基于HTTP的服务器向客户端单向推送实时数据的轻量级协议,配合浏览器原生EventSource API,可实现高效实时通信。前端通过创建EventSource对象订阅服务端流,自动处理连接、重试与数据解析;服务端设置Content-Type: text/event-stream响应头,以data:前缀发送JSON/文本数据,双换行符分隔消息。其优势在于:
-
协议简单,无需WebSocket复杂握手
-
天然支持断线重连
-
兼容主流浏览器
-
适合实时通知、股票行情等单向推送场景。后端实现需注意保持长连接(如循环发送注释保持活跃),前端需监听message事件处理数据,并通过error事件监控连接状态。相比轮询,SSE显著降低延迟与资源消耗,是Web实时应用的优选方案之一。
然而当前端通过EventSource API发起请求时有几个限制:只允许传递的参数是url和withCredentials,因此:
-
无法传递请求体:你必须在URL内编码执行请求所需的所有信息,而在大多数浏览器中,URL的长度是有限制的(不同浏览器可能还不一样)。
-
无法传递自定义请求头。
-
只能发起GET请求——无法指定其他方法。
-
如果连接中断,你无法控制重试策略:浏览器会默默地为你重试几次然后停止,这对于任何健壮的应用程序来说都远远不够。
本篇文章我们将介绍一个开源组件fetch-event-source,该组件在发起事件源请求时,同时拥有Fetch API所提供的所有功能。
接下来,我们将完整实现一个基于SSE(Server-Sent Events)与Fetch-Event-Source API结合的实时通信示例。
2. 实战案例
2.1 准备环境
@RestController
@RequestMapping("/api")
public class SseController {
private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>() ;
@GetMapping(path = "/sse/{username}", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handler(@PathVariable String username) throws Exception {
SseEmitter sse = new SseEmitter() ;
emitters.put(username, sse) ;
sse.send(new R(0, "欢迎," + username), MediaType.APPLICATION_JSON) ;
return sse ;
}
@PostMapping(path = "/sse", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handler(@RequestBody Map<String, Object> data) throws Exception {
System.err.printf("收到请求数据: %s%n", data) ;
SseEmitter sse = new SseEmitter() ;
String username = data.get("u