SSE结合SpringBoot

SSE是一门单向的消息通知,主要用于服务端主动推送消息到客户端,当然WebSocket也可以做到这个效果,但是WebSocket是双向的,比SSE更加笨重了一点,SSE技术可以用于解决避免轮询,消息主动推送等方面的问题。
https://blog.youkuaiyun.com/qq_33503359/article/details/108826591

### Spring Boot 中实现 SSE (Server-Sent Events) 在 Spring Boot 应用程序中,可以通过 `Controller` 和特定的响应类型来轻松实现 Server-Sent Events 功能。以下是具体的实现方法: #### 使用 `TextEventStream` 响应类型 Spring 提供了一个专门用于处理 SSE 的 MIME 类型——`text/event-stream`。通过返回一个 `Flux<String>` 或者 `SseEmitter` 对象,可以向客户端发送连续的数据流。 下面是一个基于 `Flux<String>` 的简单示例[^3]: ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.time.Duration; @RestController public class SseController { @GetMapping(value = "/stream", produces = "text/event-stream") public Flux<String> streamEvents() { return Flux.interval(Duration.ofSeconds(1)) .map(sequence -> "data: Event number " + sequence + "\n\n"); } } ``` 在这个例子中,`Flux.interval` 创建了一个每秒触发一次的时间序列事件,并将其转换为字符串形式的消息。这些消息将以 SSE 格式传递给客户端。 #### 使用 `SseEmitter` 手动管理连接 如果需要更精细地控制每个请求的生命周期,则可以选择使用 `SseEmitter` 来手动管理连接状态。这种方式适合于复杂场景下的数据推送需求[^4]: ```java import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @Controller public class ManualSseController { private final Map<Long, SseEmitter> emitters = new ConcurrentHashMap<>(); @GetMapping("/subscribe/{id}") public SseEmitter subscribe(@PathVariable Long id) throws InterruptedException { SseEmitter emitter = new SseEmitter(); // 添加到缓存以便后续操作 emitters.put(id, emitter); // 设置超时时间(可选) emitter.onCompletion(() -> emitters.remove(id)); emitter.onTimeout(() -> { try { emitter.send(SseEmitter.event().reconnectTime(10_000).name("retry")); } catch (Exception e) {} }); // 模拟异步任务 CompletableFuture.runAsync(() -> sendUpdates(emitter)); return emitter; } private void sendUpdates(SseEmitter emitter) { IntStream.rangeClosed(1, 5).forEach(i -> { try { Thread.sleep(2000); emitter.send(SseEmitter.event() .id(String.valueOf(System.currentTimeMillis())) .name("update-event") .data("Update Number:" + i)); } catch (Exception ex) { System.err.println(ex.getMessage()); } }); } } ``` 上述代码展示了如何利用 `SseEmitter` 构建更加灵活的服务端推模式。它允许开发者定义何时以及怎样发送更新通知给订阅它的前端应用。 --- ### 客户端接收 SSE 数据 为了测试上面创建好的服务端接口,在 HTML 页面里可以直接借助 JavaScript API 接收来自服务器的信息: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SSE Example</title> </head> <body> <ul id="event-list"></ul> <script type="text/javascript"> const eventSource = new EventSource('/stream'); eventSource.onmessage = function(event) { const li = document.createElement('li'); li.textContent = 'Received message:' + event.data; document.getElementById('event-list').appendChild(li); }; // 错误监听器 eventSource.onerror = function(err){ console.error(`Error occurred ${err}`); }; </script> </body> </html> ``` 此脚本会持续显示从 `/stream` 路径接收到的新消息列表项。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值