更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

Spring WebFlux之SSE服务器发送事件
- 1. 什么是 SSE?
- 2. Spring Boot 3 响应式编程与 SSE
- 3. 实现 SSE 的基本步骤
- 3.1 创建 Spring Boot 项目
- 3.2 实现服务端推送 SSE 事件流
- 3.3 客户端接收 SSE 数据
- 4. 测试 SSE
- 5. 优化与扩展
- 5.1 增加随机数据推送
- 5.2 增加心跳检测(Ping)
- 5.3 使用 `MediaType.TEXT_EVENT_STREAM` 响应
- 6. SSE 与 WebSocket 的对比
- 7. 总结
ChatGPT 刚出的时候,让大伙很好奇的是它是如何实现的逐字输出的?答案就是 SSE (服务器发送事件)。
4. 测试 SSE
运行 Spring Boot 应用,并访问 /sse/stream
,可以看到服务器每秒钟向客户端推送一次当前时间信息。
onmessage
:处理服务器发送的消息,并将消息显示在页面上。ServerSentEvent.builder()
:构建 ServerSentEvent
对象,它可以包含 id
、为什么选择响应式编程实现 SSE?
传统的阻塞式编程在处理长连接(如 SSE)时可能会占用大量服务器资源。实时通知、为此,SSE 规范推荐发送 “ping” 消息来保持连接活跃。响应式编程通过非阻塞 I/O 操作,不仅可以高效处理长时间的连接,还能在有新数据时立即推送给客户端。与传统的 HTTP 请求-响应模型不同,SSE 是单向的,服务器可以持续不断地向客户端发送数据,而客户端通过一次长连接持续接收这些更新。这就验证了 SSE 在 Spring Boot 3 中的实现。股票价格更新等场景。在客户端发起与服务器的 SSE 长连接。在实际项目中,SSE 非常适合用于推送实时数据或监控信息,尤其在需要轻量且可靠的单向通信时。
3. 实现 SSE 的基本步骤
我们将通过以下步骤实现一个简单的 SSE 服务端推送应用:
- 创建 Spring Boot 项目并引入 WebFlux 依赖。服务器通过
/sse/stream
推送事件。示例控制器
packagecom.coderjia.boot3webflux.controller;importorg.springframework.http.codec.ServerSentEvent;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.GetMapping;importreactor.core.publisher.Flux;importjava.time.Duration;importjava.time.LocalTime;@ControllerpublicclassSseController{@GetMapping("/sse/stream")publicFlux<ServerSentEvent<String>>streamSse(){returnFlux.interval(Duration.ofSeconds(1)).map(sequence ->ServerSentEvent.<String>builder().id(String.valueOf(sequence)).event("periodic-event").data("Current time: "+LocalTime.now()).build());}}
解释
Flux.interval(Duration.ofSeconds(1))
:创建一个每秒发出事件的响应式流。Spring WebFlux 是 Spring Boot 3 中用于构建响应式应用的核心框架,它可以无缝集成 SSE,为我们提供简单高效的服务器推送功能。通过 Spring WebFlux 和 Project Reactor,SSE 的实现可以以非阻塞的方式运行,极大提升了应用的并发处理能力。
5.2 增加心跳检测(Ping)
SSE 连接如果长时间没有数据传输,可能会被中断。可以通过 ServerSentEvent
的 comment()
来发送心跳信息:
@GetMapping("/sse/stream-with-ping")publicFlux<ServerSentEvent<String>>streamWithPing(){returnFlux.interval(Duration.ofSeconds(1)).map(sequence ->{if(sequence %5==0){returnServerSentEvent.<String>builder().comment("ping").build();}else{returnServerSentEvent.<String>builder().data("Current time: "+LocalTime.now()).build();}});}
5.3 使用 MediaType.TEXT_EVENT_STREAM
响应
虽然 ServerSentEvent
是处理 SSE 的标准类,但你也可以直接返回 Flux<T>
,Spring 会自动将其转换为事件流。SSE 提供了一种轻量级的服务器推送数据给客户端的方式,适合用于监控、
- 编写客户端接收 SSE 数据。假设我们希望推送随机的股票价格,我们可以这样修改:
@GetMapping("/sse/stocks")publicFlux<ServerSentEvent<String>>streamStockPrices(){returnFlux.interval(Duration.ofSeconds(1)).map(sequence ->ServerSentEvent.<String>builder().id(String.valueOf(sequence)).event("stock-update").data("Stock price: $"+ThreadLocalRandom.current().nextInt(100,200)).build());}
在这个例子中,每秒推送一次随机的股票价格更新。