Spring Boot整合SSE实时通信

server/2025/1/12 22:16:01/

服务器发送事件(Server-Sent Events, SSE)是一种让网页实时更新的技术。想象一下,您正在浏览一个网页,而这个网页需要在有新信息时自动更新,比如新闻网站的最新消息、社交媒体的通知或股票市场的价格变动。SSE使得这种实时更新成为可能,并且它是通过普通的HTTP连接实现的,这意味着它不需要任何特殊的协议或复杂的设置。

SSE的主要特点

  • 基于HTTP:SSE使用标准的HTTP协议来通信,因此它很容易集成到现有的网络架构中,无需额外配置。

  • 单向数据流:与WebSocket不同,SSE只允许服务器向客户端推送数据,而不能反过来。这对于只需要从服务器接收更新的场景非常有用,例如直播评论或通知提醒。

  • 自动重连:如果由于某种原因连接中断了,浏览器会自动尝试重新连接到服务器,确保用户不会错过任何更新。

  • 自定义事件类型:除了基本的数据推送外,SSE还允许服务器发送特定类型的事件,这样客户端就可以根据不同的事件类型做出相应的反应。

  • 轻量级和简单:相比其他如WebSocket等技术,SSE的实现更为简单,适合不需要双向通信的应用场景。对于开发者来说,这意味着更少的代码和更容易维护的系统。

添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

创建SSE控制器

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.web.bind.annotation.CrossOrigin;
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;
@CrossOrigin
@RestController
@RequestMapping("sse")
public class SseController {private final ExecutorService executorService = Executors.newCachedThreadPool();@GetMapping("/handleSse")public SseEmitter handleSse() {SseEmitter emitter = new SseEmitter();executorService.execute(() -> {try {for (int i = 0; i < 10; i++) {emitter.send(SseEmitter.event().name("message").data("数据库来消息了" + i));Thread.sleep(1000);}emitter.complete();} catch (IOException | InterruptedException e) {emitter.completeWithError(e);}});return emitter;}
}

客户端实现

<!DOCTYPE html>
<html>
<body>
<h1>SSE Demo</h1>
<div id="messages"></div>
<button id="connectButton">连接</button>
<button id="disconnectButton" disabled>断开连接</button><script>let eventSource = null;const messages = document.getElementById('messages');const connectButton = document.getElementById('connectButton');const disconnectButton = document.getElementById('disconnectButton');function connect() {if (eventSource) return; // 如果已经连接,则不重复创建eventSource = new EventSource('http://localhost:8081/items/handleSse');eventSource.onmessage = function(event) {const message = document.createElement('p');message.textContent = event.data;messages.appendChild(message);};eventSource.onerror = function(error) {console.error('EventSource failed:', error);disconnect(); // 在发生错误时也尝试断开连接};// 禁用连接按钮,启用断开连接按钮connectButton.disabled = true;disconnectButton.disabled = false;}function disconnect() {if (!eventSource) return; // 如果没有连接,则不执行任何操作eventSource.close();eventSource = null;// 启用连接按钮,禁用断开连接按钮connectButton.disabled = false;disconnectButton.disabled = true;}// 给按钮添加事件监听器connectButton.addEventListener('click', connect);disconnectButton.addEventListener('click', disconnect);
</script>
</body>
</html>

SSE(服务器发送事件)的优缺点及适用场景

优点
  • 简单易用:与WebSocket相比,SSE不需要复杂的握手过程。它的API设计直观,开发者可以更快速地上手。
  • 广泛的浏览器支持:几乎所有现代浏览器都支持SSE,包括手机和平板上的浏览器,这意味着它几乎可以在任何设备上工作。
  • 高效能和低延迟:相较于传统的轮询方式,SSE减少了不必要的请求次数,降低了服务器负担,并提高了数据更新的速度。
  • 自动重连功能:当网络连接中断时,浏览器会自动尝试重新连接到服务器,这简化了开发者的代码。
缺点
  • 单向通信限制:SSE只允许服务器向客户端推送信息,如果需要从客户端向服务器发送数据,则必须使用其他方法或技术。
  • 依赖HTTP长连接:虽然SSE优化了数据传输,但它的实现仍然基于HTTP连接,这可能在网络条件不佳或者通过某些代理服务器时遇到问题。
适用场景

SSE非常适合用于那些只需要服务器向客户端推送实时更新的应用场景,例如:

  • 实时新闻更新
  • 股票价格变动通知
  • 社交媒体动态提醒
  • 实时评论流
  • 系统状态监控
SSE vs. 轮询 vs. WebSocket
  • SSE与轮询的区别:传统轮询是客户端定时询问服务器是否有新数据,这种方式不仅增加了服务器的压力,也带来了较高的延迟。而SSE让服务器在有新数据时主动推送给客户端,减少了不必要的请求,提升了性能和用户体验。

  • SSE与WebSocket的对比

    • 通信方向:WebSocket支持双向通信,意味着客户端和服务器都可以随时发送消息;而SSE仅允许服务器向客户端推送信息。
    • 协议基础:WebSocket使用了自己的协议,而SSE基于标准的HTTP/HTTPS协议,使得SSE更容易部署并且更易于调试。
    • 连接管理:WebSocket建立后保持连接开放,直到被显式关闭;而SSE会在每次事件推送后自然断开,然后根据需要重新建立连接。
    • 兼容性和安全性:由于SSE基于HTTP协议,因此它在网络穿越方面表现得更好,并且能够更好地利用现有的安全机制(如HTTPS)。
选择建议
  • 轮询:适合于对实时性要求不高、只需要偶尔检查更新的场景。不过,这种方式会增加服务器的负载。
  • SSE:对于需要实时推送更新但不涉及双向通信的应用来说,SSE是一个很好的选择,因为它实现简单,而且浏览器兼容性好。
  • WebSocket:适用于需要频繁双向通信的应用,比如在线聊天室或多人在线游戏。

总之,选择哪种技术取决于您的具体需求和技术栈。如果您只需要服务器向客户端推送信息,并希望实现起来尽可能简单,那么SSE可能是最佳的选择。


http://www.ppmy.cn/server/157863.html

相关文章

Go语言开发中如何处理海量文件的并发读写问题 ?

在Go语言开发中处理海量文件的并发读写问题是一个复杂但常见的需求&#xff0c;特别是在大数据处理、日志分析、文件服务器等场景中。为了高效地处理这些任务&#xff0c;我们需要综合考虑并发控制、I/O性能优化、内存管理、错误处理等多个方面。以下将详细探讨如何在Go语言中实…

鼠标过滤驱动

文章目录 概述代码参考资料 概述 其编写过程大体与键盘过滤驱动相似&#xff0c;只需要切换一下附加的目标设备以及创建的设备类型等。但在该操作后依然无法捕获到Vmware创建的win7操作系统的鼠标irp信息&#xff0c;于是通过在获取鼠标驱动&#xff0c;遍历其所有的设备进而附…

2025“华数杯”国际数学建模大赛A他能游得更快吗Can He Swim Faster(完整思路 模型 源代码 结果分享)

在2024年巴黎奥运会上&#xff0c;中国游泳运动员潘振磊凭借出色表现成为全球关注的焦点。年仅19岁的他以46秒40的成绩赢得了男子100米自由泳冠军&#xff0c;并创造了个人世界纪录。潘振磊和他的队友徐佳瑜、秦海阳和孙佳军在男子4x100米混合泳接力决赛中再次为中国游泳队夺得…

Linux(CentOS7)安装JDK和Maven

文章目录 CentOS软件安装方式JDK安装Maven安装 CentOS软件安装方式 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&#xff0c;修改配置即可。例如tomcatrpm(redhat package manager)安装软件已经按照redhat的包管理规范进行打包&#x…

数据库中的 DDL、DML 和 DCL

数据库中的 DDL、DML 和 DCL 在数据库的定义与操作中&#xff0c;DDL、DML 和 DCL 是三个核心概念&#xff0c;分别用于不同层面的数据库管理与操作。 1. DDL&#xff08;Data Definition Language&#xff09; - 数据定义语言 定义 DDL 用于定义和管理数据库的结构或模式。…

基于spingboot+html技术的博客网站

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

C语言gdb调试

目录 1.gdb介绍 2.设置断点 2.1.测试代码 2.2.设置函数断点 2.3.设置文件行号断点 2.4.设置条件断点 2.5.多线程调试 3.删除断点 3.1.删除指定断点 3.2.删除全部断点 4.查看变量信息 4.1.p命令 4.2.display命令 4.3.watch命令 5.coredump日志 6.总结 1.gdb介绍…

深入探索AI核心模型:CNN、RNN、GAN与Transformer

在人工智能的飞速发展中&#xff0c;众多深度学习模型和算法不断涌现&#xff0c;推动了许多领域的进步。特别是在图像识别、自然语言处理、生成建模等方向&#xff0c;AI模型的应用越来越广泛。本文将介绍几种最常用的AI模型&#xff0c;包括卷积神经网络&#xff08;CNN&…