引言
在这个信息爆炸的时代,谁不想让自己的网页像直播一样实时更新呢?想象一下,你在看一个美食博客,突然弹出一条消息:“厨师刚刚把烤箱预热到了200°C!”是不是觉得特别酷?这就是 Server-Sent Events(简称 SSE)的魅力所在。
什么是 Server-Sent Events?
Server-Sent Events 就像是你的网页和服务器之间的“小喇叭”,服务器可以通过这个“小喇叭”随时向你的网页发送消息,而你完全不需要不停地刷新页面。它的主要优点包括:
- 简单:实现起来比你想象的简单多了,不需要复杂的握手过程。
- 轻量:只需要一个 HTTP 连接,不会让你的电脑喘不过气来。
- 兼容性好:大多数现代浏览器都支持 SSE,不用担心用户用的是什么奇葩浏览器。
SseEmitter 是什么?
在 Spring Boot 中,SseEmitter 是一个用来实现 SSE 的神器。它就像一个魔法棒,轻轻一挥,你的服务器就能向客户端发送实时数据了。接下来,我们通过一个贴近生活的例子来展示如何使用 SseEmitter。
示例:实时厨房更新
假设你是一个美食博主,正在直播制作一道美味的蛋糕。你需要将每个步骤的更新实时推送到前端页面,让观众们知道你正在做什么。我们将使用 SseEmitter 来实现这个功能。
1. 创建控制器
首先,我们在 Spring Boot 项目中创建一个控制器,用于处理 SSE 请求。
package com.timechee.module.infra.controller.admin.qrCode;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@RestController
@RequestMapping("/kitchen")
@EnableScheduling
public class KitchenController {
private final ConcurrentMap<Long, SseEmitter> emitters = new ConcurrentHashMap<>();
@GetMapping("/stream")
public SseEmitter streamKitchenUpdates() {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE); // 设置超时时间为 Long.MAX_VALUE
emitters.put(System.currentTimeMillis(), emitter);
emitter.onCompletion(() -> emitters.remove(emitters.keySet().toArray()[0]));
emitter.onTimeout(() -> emitters.remove(emitters.keySet().toArray()[0]));
sendKitchenUpdate(emitter, "The kitchen live broadcast has begun");
return emitter;
}
@Scheduled(fixedRate = 5000) // 每5秒发送一次厨房更新
public void sendKitchenUpdates() {
String kitchenUpdate = getLatestKitchenUpdate();
for (SseEmitter emitter : emitters.values()) {
sendKitchenUpdate(emitter, kitchenUpdate);
}
}
private void sendKitchenUpdate(SseEmitter emitter, String update) {
try {
emitter.send(SseEmitter.event()
.id(String.valueOf(System.currentTimeMillis()))
.name("kitchen")
.data(update));
} catch (IOException e) {
emitter.completeWithError(e);
}
}
private String getLatestKitchenUpdate() {
// 模拟从厨房获取最新更新
return new Date() + " is stirring the batter, and the aroma is overflowing!";
}
}
解释
- 控制器:
streamKitchenUpdates方法创建一个SseEmitter对象,并将其存储在一个ConcurrentMap中。这样,我们可以在定时任务中访问这些SseEmitter对象。sendKitchenUpdate方法用于发送厨房更新。它使用SseEmitter.event()方法创建一个事件对象,并将其发送给客户端。sendKitchenUpdates方法是一个定时任务,每5秒调用一次,获取最新的厨房信息并发送给所有连接的客户端。getLatestKitchenUpdate方法模拟从厨房获取最新更新。
结语
通过 SseEmitter,你可以轻松地实现服务器向客户端的实时数据推送。无论是厨房直播、股票行情还是其他实时数据,SseEmitter 都能帮助你高效地实现这一功能。希望这篇博客能让你对 SseEmitter 有更深入的了解,并在实际项目中应用起来!
如果你觉得这篇文章有趣,不妨分享给你的朋友们,让他们也一起来感受 SseEmitter 的魅力吧!如果有任何问题或建议,欢迎随时留言交流。记得给我点个赞哦,你的支持是我最大的动力!
希望你喜欢这篇博客!如果有任何问题或建议,欢迎随时留言交流。