Spring Boot 整合 SSE(Server-Sent Events)

[复制链接]
发表于 2025-10-31 00:20:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1、简述

SSE(Server-Sent Events)是一种基于HTTP协议的单向通讯机制,答应服务器向欣赏器连续发送实时更新。与WebSocket差别,SSE更简单,利用HTTP/1.1协议即可,不必要额外的协议升级。
SSE的特点:

  • 单向通讯:服务器推送数据给客户端,客户端无法向服务器发送消息。
  • 简单易用:基于HTTP协议,无需复杂的设置。
  • 欣赏器支持:当代欣赏器大多内置支持(如Chrome、Edge、Firefox等)。
2、Spring Boot 中的SSE实现

2.1 添加依靠
SSE无需额外的依靠,Spring Boot自带对SSE的支持。创建一个Spring Boot项目即可。
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
复制代码
2.2 实现后端接口
利用MediaType.TEXT_EVENT_STREAM_VALUE作为返回范例即可开启SSE。以下代码是一个简单的实现。
  1. package com.example.sse.controller;
  2. import org.springframework.http.MediaType;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. import java.time.LocalTime;
  6. import java.util.concurrent.Executors;
  7. import java.util.concurrent.TimeUnit;
  8. import java.util.stream.Stream;
  9. @RestController
  10. public class SseController {
  11.     @GetMapping(value = "/sse/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
  12.     public Stream<String> stream() {
  13.         // 模拟数据流
  14.         return Stream.generate(() -> "当前时间:" + LocalTime.now())
  15.                      .limit(10); // 限制10条消息
  16.     }
  17. }
复制代码
2.3 设置超时时间(可选)
默认情况下,Spring Boot的相应会超时。可以在application.properties中调解超时时间:
  1. server.servlet.session.timeout=30s
  2. spring.mvc.async.request-timeout=30000
复制代码
2.4 前端实现
SSE在前端通过EventSource对象实现。以下是一个简单的前端示例:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>SSE Example</title>
  6. </head>
  7. <body>
  8.     <h1>实时消息</h1>
  9.     <div id="messages"></div>
  10.     <script>
  11.         const eventSource = new EventSource('/sse/stream');
  12.         eventSource.onmessage = function(event) {
  13.             const messagesDiv = document.getElementById('messages');
  14.             const newMessage = document.createElement('p');
  15.             newMessage.textContent = event.data;
  16.             messagesDiv.appendChild(newMessage);
  17.         };
  18.         eventSource.onerror = function() {
  19.             console.error('SSE连接出错,正在尝试重连...');
  20.             eventSource.close();
  21.         };
  22.     </script>
  23. </body>
  24. </html>
复制代码
3、高级实践
利用Spring Scheduler推送数据,在实际场景中,大概必要定时向客户端推送数据。比方,监控监控体系定时更新。
  1. package com.example.sse.service;
  2. import org.springframework.http.MediaType;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  5. import java.io.IOException;
  6. import java.util.concurrent.CopyOnWriteArrayList;
  7. @Service
  8. public class SsePushService {
  9.     private final CopyOnWriteArrayList<SseEmitter> emitters = new CopyOnWriteArrayList<>();
  10.     public SseEmitter subscribe() {
  11.         SseEmitter emitter = new SseEmitter(30_000L);
  12.         emitters.add(emitter);
  13.         emitter.onCompletion(() -> emitters.remove(emitter));
  14.         emitter.onTimeout(() -> emitters.remove(emitter));
  15.         return emitter;
  16.     }
  17.     public void pushMessage(String message) {
  18.         for (SseEmitter emitter : emitters) {
  19.             try {
  20.                 emitter.send(message, MediaType.TEXT_PLAIN);
  21.             } catch (IOException e) {
  22.                 emitters.remove(emitter);
  23.             }
  24.         }
  25.     }
  26. }
复制代码
创建一个控制器订阅和推送消息:
  1. package com.example.sse.controller;
  2. import com.example.sse.service.SsePushService;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. public class SsePushController {
  7.     private final SsePushService ssePushService;
  8.     public SsePushController(SsePushService ssePushService) {
  9.         this.ssePushService = ssePushService;
  10.     }
  11.     @GetMapping("/sse/subscribe")
  12.     public SseEmitter subscribe() {
  13.         return ssePushService.subscribe();
  14.     }
  15.     @GetMapping("/sse/push")
  16.     public void pushMessage() {
  17.         ssePushService.pushMessage("当前时间:" + System.currentTimeMillis());
  18.     }
  19. }
复制代码
注意事项:

  • 欣赏器兼容性:SSE不支持IE,但当代欣赏器支持精良。
  • 毗连断开处置惩罚:可通过EventSource的onerror事故重新毗连。
  • 性能标题:对大量订阅者时,需思量利用分布式消息队列优化(如Kafka)。
  • 超时时间:默认30秒超时,必要根据实际需求调解。
4、实用场景


  • 实时关照:如监控监控体系的告警推送。
  • 实时更新:如股票行情、体育比分。
  • 消息流:如体系日志日志、任务进度。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表