Server Send Event(基于Http协议的单向消息通信)

简介

Server-Sent Events(SSE)是一种简单的技术,允许服务器向客户端推送实时更新。在Spring Boot项目中,我们可以使用SseEmitter类来实现SSE功能。本文将详细介绍如何在Spring Boot项目中使用SSE,并给出一个使用示例。

核心原理

首先,客户端通过浏览器向服务器发送一个SSE请求,当服务器收到这个SSE请求后,会建立一个持久的HTTP连接,并将响应的Content-Type设置为text/event-stream。然后,服务器就可以通过这条已经建立的连接向客户端持续发送数据了。每个数据都由一个或多个字段组成,如event、data、id等。需要注意的是,SSE是单向通信协议,只能从服务器端向客户端发送数据。

引入项目依赖

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

创建SSE的使用工具类

public class SseEmitterUtil {private final static Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();private final static AtomicInteger count = new AtomicInteger();/*** 创建SSE连接* Connect sse emitter.** @param clientId the client id* @return the sse emitter*/public static SseEmitter connect(String clientId) {try {// 设置超时时间,0表示不过期。默认30秒SseEmitter sseEmitter = new SseEmitter(0L);// 注册回调sseEmitter.onCompletion(() -> {log.info("客户端正常关闭,clientId = {}", clientId);removeClientId(clientId);});sseEmitter.onError(throwable -> {log.error("连接出现异常,准备关闭,clientId = {}", clientId);removeClientId(clientId);});sseEmitter.onTimeout(() -> {log.info("连接已超时,准备关闭,clientId = {}", clientId);removeClientId(clientId);});sseEmitterMap.put(clientId, sseEmitter);count.getAndIncrement();log.info("连接成功,客户端连接总数:{}", count.get());return sseEmitter;} catch (Exception e) {log.info("创建新的sse连接异常,clientId:{}", clientId);log.error(e.toString());}return null;}/*** 给指定用户发送消息* Send message.** @param clientId the client id    客户端id* @param message  the message*/public static void sendMessage(String clientId, String message) {if (sseEmitterMap.containsKey(clientId)) {try {sseEmitterMap.get(clientId).send(message);} catch (IOException e) {log.error("clientId:[{}],推送数据:{},推送异常:{}", clientId, message, e.getMessage());removeClientId(clientId);}}}/*** 断开连接* Disconnect.** @param clientId the client id*/public static void disconnect(String clientId) {if (sseEmitterMap.containsKey(clientId)) {log.info("连接断开,clientId:{}", clientId);sseEmitterMap.get(clientId).complete();} else {log.error("不存在clientId为{}的客户端连接", clientId);}}/*** 移除连接客户端* Remove client id.** @param id the id 客户端连接ID*/private static void removeClientId(String id) {sseEmitterMap.remove(id);count.getAndDecrement();log.info("剩余客户端连接数:{}", count.get());}}

工具类的使用

@RequestMapping("/sse")
public class SseController {/*** 连接SSE* Push sse emitter.** @param clientId the client id* @return the sse emitter*/@GetMapping("/connect")public SseEmitter push(String clientId) {return SseEmitterUtil.connect(clientId);}/*** 消息推送* Push.** @param clientId the client id* @param content  the content*/@GetMapping("/push")public void push(String clientId, String content) {SseEmitterUtil.sendMessage(clientId, content);}/*** 断开连接* Disconnect.** @param clientId the client id*/@GetMapping("/disconnect")public void disconnect(String clientId) {SseEmitterUtil.disconnect(clientId);}
}

PS:在使用过程是前后端约定好不同的场景使用特定的clientId进行消息传输,使用完毕调用关闭连接的接口即可

使用及优势分析

  • 只需要服务端向客户端单向通信的场景下可以使用
  • SSE 实现简单开发成本低,无需引入其他组件;WebSocket传输数据需做二次解析,开发门槛高一些
  • SSE 默认支持断线重连;WebSocket则需要自己实现
  • SSE 只能传送文本消息,二进制数据需要经过编码后传送;WebSocket默认支持传送二进制数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(九)上市企业实施IPD成功案例分享之——欧普

LED通用照明应用是LED照明应用市场的第一驱动力&#xff0c;由于LED照明技术发展迅速&#xff0c;以及成本快速下降&#xff0c;已成为全球主流照明光源。近年来&#xff0c;通过将智能控制模块嵌入LED通用照明终端&#xff0c;形成了具有自动控制、系统化控制等功能的智能照明…

听GPT 讲Rust源代码--library/panic_unwind

File: rust/library/panic_unwind/src/seh.rs 在Rust源代码中&#xff0c;rust/library/panic_unwind/src/seh.rs这个文件的作用是实现Windows操作系统上的SEH&#xff08;Structured Exception Handling&#xff09;异常处理机制。 SEH是Windows上的一种异常处理机制&#xff…

【Webpack】加载其他型模块

非模块化文件 非模块化文件指的是并不遵循任何一种模块标准的文件。 最常见的就是在 script标签引用jQuey及其各种插件 如何使用 Webpack打包这类文件呢? 其实只要直接引人即可&#xff0c;如: import ./jquery.min.js;但假如我们引人的非模块化文件是以隐式全局变量声明的方…

mongodb启动失败

● mongodb.service - High-performance, schema-free document-oriented database Loaded: loaded (/etc/systemd/system/mongodb.service; disabled; vendor preset: disabled) Active: inactive (dead) 1月 02 10:18:10 lcy mongod[7013]: ERROR: child process fail…

EDI 项目推进流程

EDI 需求确认 交易伙伴发来EDI对接邀请&#xff0c;企业应该如何应对&#xff1f; 首先需要确认EDI需求&#xff0c;通常包括传输协议和报文标准以及传输的业务单据类型。可以向交易伙伴发送以下内容&#xff1a; &#xff08;中文版&#xff09; 与贵司建立EDI连接需要使用…

软件黑盒测试

软件黑盒测试是一种测试方法&#xff0c;它不考虑被测试的软件的内部结构和代码&#xff0c;只关注输入和输出。黑盒测试的目的是验证软件是否符合规格说明书、用户需求和功能规范等要求。通常&#xff0c;黑盒测试包括以下几个步骤&#xff1a; 确定测试目标&#xff1a;确定测…

【温故而知新】vue组件间通信的实现方式

概念 Vue组件间通信的实现方式有以下几种: 父子组件通信:父组件可以通过props属性将数据传递给子组件,子组件可以通过$emit方法触发父组件定义的事件。子组件访问根组件:可以使用provide/inject来实现子组件访问根组件的数据。兄弟组件通信:可以通过一个共同的父组件作为…

【没有哪个港口是永远的停留~论文解读】stable diffusion

了解整个流程&#xff1a; 【第一部分】输入图像 x &#xff08;W*H*3的RGB图像&#xff09;【第一部分】x 经过编码器 生成 (latent 空间的表示) h*w*c (具体设置多少有实验)【第二部分】 逐步加噪得到 &#xff0c;和噪声标签【第二部分】由 Unet&#xff08; &#xff…

Kubernetes(k8s):Namespace详解

Kubernetes&#xff08;k8s&#xff09;&#xff1a;Namespace详解 一、Namespace简介1.1 什么是Namespace1.2 Namespace的作用1.3 命名空间的分类 二、创建和管理Namespace2.1 创建Namespace2.2 管理Namespace 三、Namespace的实战应用3.1 部署多个项目3.2 环境隔离3.3 资源配…

从零开始配置kali2023环境:配置jupyter的多内核环境

在kali2023上面尝试用anaconda3&#xff0c;anaconda2安装实现配置jupyter的多内核环境时出现各种问题&#xff0c;现在可以通过镜像方式解决 1. 搜索镜像 ┌──(holyeyes㉿kali2023)-[~] └─$ sudo docker search anaconda ┌──(holyeyes㉿kali2023)-[~] └─$ sudo …

C++初阶——权限与继承

目录 一、C权限方面的问题 1.访问权限 2.继承机制 二、Cconst引用 const引用有以下几个特点 临时对象引用 常量引用成员变量 二、c引用空间相关问题 三.auto 一、C权限方面的问题 【C入门】访问权限管控和继承机制详解_权限继承功能-CSDN博客文章浏览阅读840次。(2)但…

uniapp-H5项目的坑

先推荐个插件库-非常好用&#xff1a;https://ext.dcloud.net.cn/ 一、uniapp h5 适配pc端 1、问题&#xff1a;屏幕尺寸在400px~960px之间页面排版错乱 2、解决方法&#xff1a;在page.json文件中 "globalStyle": {"navigationStyle": "custom&quo…

YOLOv8训练自己的数据集(超详细)

一、准备深度学习环境 本人的笔记本电脑系统是&#xff1a;Windows10 YOLO系列最新版本的YOLOv8已经发布了&#xff0c;详细介绍可以参考我前面写的博客&#xff0c;目前ultralytics已经发布了部分代码以及说明&#xff0c;可以在github上下载YOLOv8代码&#xff0c;代码文件夹…

LVM和磁盘配额

一&#xff1a;LVM概述&#xff1a; LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。 能够在保持现有数据不变的情况下&#xff0c;动态调整磁盘容量&#xff0c;从而提高磁盘管理的灵活性 /boot 分区用于存放引导文件&#xff0c;不能基于LVM创建…

MongoDB vs MySQL:项目选择哪一个数据库系统?

由于市场上有各种可用的数据库&#xff0c;用户经常会就MongoDB与MySQL进行辩论&#xff0c;以找出更好的选择。 使用MySQL等关系数据库的组织在根据不断变化的需求管理和存储数据时可能会面临一定的困难。同时&#xff0c;新公司想知道选择什么数据库&#xff0c;这样他们就不…

【ArcGIS微课1000例】0085:甘肃省白银市平川区4.9级地震震中位置图件制作

据中国地震台网正式测定,12月31日22时27分在甘肃白银市平川区发生4.9级地震,震源深度10公里,震中位于北纬36.74度,东经105.00度。 文章目录 一、白银市行政区划图1. 县级行政区2. 乡镇行政区二、4.9级地震图件制作1. 震中位置2. 影像图3. 震中三维地形一、白银市行政区划图…

【LLM 】7个基本的NLP模型,为ML应用程序赋能

在上一篇文章中&#xff0c;我们已经解释了什么是NLP及其在现实世界中的应用。在这篇文章中&#xff0c;我们将继续介绍NLP应用程序中使用的一些主要深度学习模型。 BERT 来自变压器的双向编码器表示&#xff08;BERT&#xff09;由Jacob Devlin在2018年的论文《BERT:用于语言…

数据结构初阶之栈和队列(C语言版)

数据结构初阶之栈和队列&#xff08;C语言版&#xff09; ✍栈♈栈的结构设计♈栈的各个接口的实现&#x1f47a;StackInit(初始化)&#x1f47a;push&#xff08;入栈&#xff09;&#x1f47a;pop&#xff08;出栈&#xff09;&#x1f47a;获取栈顶元素&#x1f47a;获取栈中…

软件工程期末总结

软件工程期末总结 软件危机出现的原因软件生命周期软件生命周期的概念生命周期的各个阶段 软件开发模型极限编程 可行性研究与项目开发计划需求分析结构化分析的方法结构化分析的图形工具软件设计的原则用户界面设计结构化软件设计面向对象面向对象建模 软件危机出现的原因 忽视…

7.13N皇后(LC51-H)

算法&#xff1a; N皇后是回溯的经典题 画树&#xff1a; 假设N3 皇后们的约束条件&#xff1a; 不能同行不能同列不能同斜线 回溯三部曲&#xff1a; 1.确定函数参数和返回值 返回值&#xff1a;void 参数&#xff1a; int n&#xff1a;题目给出&#xff0c;N皇后的…