当前位置: 首页> 财经> 金融 > 天津建设工程信息网怎么注册_装修网站加盟骗局_线上营销的方式_江门关键词排名工具

天津建设工程信息网怎么注册_装修网站加盟骗局_线上营销的方式_江门关键词排名工具

时间:2025/7/10 19:03:43来源:https://blog.csdn.net/xujun738/article/details/147223198 浏览次数:1次
天津建设工程信息网怎么注册_装修网站加盟骗局_线上营销的方式_江门关键词排名工具

前言

在现代Web应用中,实时消息推送已成为提升用户体验的关键功能。无论是即时聊天、通知提醒还是实时数据更新,都需要一种高效的服务器到客户端的通信机制。本文将详细介绍如何使用Server-Sent Events (SSE)技术实现后端向前端的实时消息推送,并提供一个完整的实现方案。

什么是SSE?

Server-Sent Events (SSE) 是一种允许服务器向客户端推送实时更新的Web技术。与WebSocket不同,SSE是基于HTTP的单向通信(服务器→客户端),实现简单且天然支持断线重连,非常适合需要服务器推送但客户端不需要频繁发送数据的场景。

SSE的主要优势:

  1. 简单易用:基于标准HTTP协议,无需额外协议

  2. 自动重连:内置断线重连机制

  3. 轻量级:相比WebSocket更轻量

  4. 文本友好:特别适合推送文本消息

完整实现方案

下面我将通过一个完整的示例来展示如何实现SSE消息推送,包括后端服务和前端界面。

1. 后端实现

1.1 SSE服务核心类
@Service
public class SseService {private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();private final ExecutorService executor = Executors.newCachedThreadPool();// 客户端订阅public SseEmitter subscribe(String clientId) {SseEmitter emitter = new SseEmitter(180_000L); // 3分钟超时// 设置各种回调emitter.onCompletion(() -> removeEmitter(clientId));emitter.onTimeout(() -> removeEmitter(clientId));emitter.onError(e -> removeEmitter(clientId));emitters.put(clientId, emitter);// 发送初始化事件try {emitter.send(SseEmitter.event().id("0").name("connect").data("Connected!"));} catch (IOException e) {removeEmitter(clientId);}return emitter;}// 广播消息给所有客户端public void broadcast(String message) {List<String> deadEmitters = new ArrayList<>();emitters.forEach((clientId, emitter) -> {executor.execute(() -> {try {if (emitter != null) {synchronized (emitter) {emitter.send(SseEmitter.event().id(String.valueOf(System.currentTimeMillis())).name("message").data(message));}}} catch (Exception e) {deadEmitters.add(clientId);}});});// 清理无效连接deadEmitters.forEach(this::removeEmitter);}// 移除指定客户端private synchronized void removeEmitter(String clientId) {SseEmitter emitter = emitters.remove(clientId);if (emitter != null) {try {emitter.complete();} catch (Exception e) {// 忽略关闭时的异常}}}// 应用关闭时清理资源@PreDestroypublic void destroy() {emitters.keySet().forEach(this::removeEmitter);executor.shutdownNow();}
}
1.2 SSE控制器
@RestController
@RequestMapping("/api/sse")
public class SseController {@Autowiredprivate SseService sseService;// 订阅接口@GetMapping("/subscribe")public SseEmitter subscribe(@RequestParam String clientId) {return sseService.subscribe(clientId);}// 测试发送消息接口@PostMapping("/send")public ResponseEntity<Void> sendMessage(@RequestParam String message) {try {sseService.broadcast(message);return ResponseEntity.ok().build();} catch (Exception e) {return ResponseEntity.internalServerError().build();}}
}

2. 前端实现

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>消息监听</title><style>#messageBox {height: 400px;overflow-y: auto;border: 1px solid #ccc;padding: 10px;margin-bottom: 10px;}.message {margin: 5px 0;padding: 5px;background-color: #f5f5f5;border-radius: 4px;}</style>
</head>
<body><h2>实时消息监听</h2><div id="messageBox"></div><div><label><input type="checkbox" id="enableVoice" checked>启用语音播报</label><button onclick="testVoice()">测试语音</button></div><script>const clientId = 'client_' + Math.random().toString(36).substr(2, 9);const messageBox = document.getElementById('messageBox');const enableVoiceCheckbox = document.getElementById('enableVoice');const synth = window.speechSynthesis;// 初始化语音合成function loadVoices() {voices = synth.getVoices();}loadVoices();if (speechSynthesis.onvoiceschanged !== undefined) {speechSynthesis.onvoiceschanged = loadVoices;}// 语音播报功能function speak(text) {if (!enableVoiceCheckbox.checked) return;synth.cancel(); // 取消之前的语音const utterance = new SpeechSynthesisUtterance(text);const chineseVoice = voices.find(voice => voice.lang.includes('zh'));if (chineseVoice) {utterance.voice = chineseVoice;}utterance.lang = 'zh-CN';utterance.onerror = (event) => {console.error('语音播报错误:', event);};synth.speak(utterance);}// 连接SSEfunction connectSSE() {const eventSource = new EventSource(`/api/sse/subscribe?clientId=${clientId}`);eventSource.addEventListener('message', function(event) {// 显示消息const messageDiv = document.createElement('div');messageDiv.className = 'message';messageDiv.textContent = event.data;messageBox.insertBefore(messageDiv, messageBox.firstChild);// 语音播报speak(event.data);});// 错误处理与重连eventSource.onerror = function(error) {console.error('SSE连接错误:', error);eventSource.close();setTimeout(connectSSE, 5000); // 5秒后重连};}// 启动连接connectSSE();// 页面隐藏时停止语音document.addEventListener('visibilitychange', function() {if (document.hidden) {synth.cancel();}});</script>
</body>
</html>

与WebSocket的对比

特性SSEWebSocket
通信方向单向(服务器→客户端)双向
协议HTTP独立协议
断线重连内置支持需手动实现
二进制数据不支持支持
浏览器兼容性IE不支持更广泛
实现复杂度简单较复杂

适用场景

SSE特别适合以下场景:

  • 服务器向客户端推送通知

  • 实时数据更新(如股票价格、体育比分)

  • 新闻/社交媒体feed更新

  • 需要简单实现的实时功能

总结

SSE提供了一种简单高效的服务器推送技术方案,本文通过完整的代码示例展示了如何从零开始实现一个功能完善的SSE推送系统。相比WebSocket,SSE在实现简单性、自动重连等方面具有明显优势,是许多实时应用场景的理想选择。

希望本文能帮助你理解并应用SSE技术。如果你有任何问题或建议,欢迎在评论区留言讨论!

关键字:天津建设工程信息网怎么注册_装修网站加盟骗局_线上营销的方式_江门关键词排名工具

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: