当前位置: 首页 > news >正文

SpringBoot整合WebSocket详解

环境:Springboot3.0.5


WebSocket介绍

WebSocket协议RFC 6455提供了一种标准化的方式,通过一个TCP连接在客户端和服务器之间建立全双工、双向的通信通道。它是一个不同于HTTP的TCP协议,但设计为在HTTP之上工作,使用80和443端口,并允许重用现有的防火墙规则。

WebSocket交互开始于一个HTTP请求,使用HTTP Upgrade header进行升级,在本例中是切换到WebSocket协议。下面的例子展示了这种交互:

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket             // ①
Connection: Upgrade           // ②
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080

①:Upgrade header头部信息

②:使用 Upgrade 连接

支持WebSocket的服务器会返回类似下面的输出,而不是通常的200状态码:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp

握手成功后,HTTP upgrade请求的TCP套接字保持打开,客户端和服务器可以继续发送和接收消息。

如果WebSocket服务器运行在web服务器(例如nginx)后面,你可能需要配置它来将WebSocket升级请求传递给WebSocket服务器。同样,如果应用程序运行在云环境中,请查看云提供商提供的有关WebSocket支持的说明。

HTTP与WebSocket

尽管WebSocket在设计上是与HTTP兼容的,而且从HTTP请求开始,但重要的是要明白,这两种协议导致了非常不同的架构和应用程序编程模型。

在HTTP和REST中,应用程序被建模为多个url。为了与应用程序交互,客户端以请求-响应的方式访问这些url。服务器根据HTTP URL、方法和首部将请求路由到适当的处理程序。

相比之下,在websocket中,初始连接通常只有一个URL。随后,所有应用程序消息都在同一个TCP连接上流动。这是一种完全不同的异步、事件驱动的消息传递架构。

WebSocket也是一种底层传输协议,与HTTP不同,它对消息内容没有任何语义规定。这意味着除非客户端和服务器在消息语义上达成一致,否则无法路由或处理消息。

WebSocket客户端和服务器可以通过HTTP握手请求的Sec-WebSocket-Protocol头部来协商使用更高级别的消息传递协议(例如STOMP)。在这种情况下,他们需要制定自己的惯例。

什么时候该使用WebSocket

WebSockets可以使网页具有动态性和交互性。然而,在许多情况下,Ajax和HTTP流或长轮询的组合可以提供简单而有效的解决方案。

例如,新闻、邮件和社交源需要动态更新,但每隔几分钟更新一次完全没问题。另一方面,协作、游戏和金融应用需要更接近实时。

延迟本身并不是决定性因素。如果消息量相对较少(例如监视网络故障),HTTP流或轮询可以提供有效的解决方案。低延迟、高频率和高容量的组合才是WebSocket的最佳选择。

还要记住,在互联网上,你无法控制的限制性代理可能会阻止WebSocket交互,要么是因为它们没有配置为传递Upgrade header,要么是因为它们关闭了看起来空闲的长连接。这意味着对防火墙内的内部应用程序使用WebSocket比面向公众的应用程序更直接。

图片

WebSocket核心API

Spring框架提供了一个WebSocket API,可以用它来编写处理WebSocket消息的客户端和服务器端应用程序。

  • WebSocketHandler

创建WebSocket服务器很简单,只需实现WebSocketHandler,或者扩展TextWebSocketHandler或BinaryWebSocketHandler。下面的例子使用了TextWebSocketHandler:

public class MessageHandler extends TextWebSocketHandler {@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) {System.out.printf("SessionId: %s, 接收到消息: %s%n", session.getId(), message.getPayload()) ;try {session.sendMessage(new TextMessage("服务端接收到消息 - " + message.getPayload())) ;} catch (IOException e) {e.printStackTrace();}}@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.printf("连接成功, 会话Id: %s, Attribute: %s%n", session.getId(), session.getAttributes()) ;}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {System.out.printf("连接关闭, 会话Id: %s, 关闭状态: %s%n", session.getId(), status.getCode() + " - " + status.getReason()) ;}}

WebSocket配置

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(messageHandler(), "/message")}@Beanpublic WebSocketHandler messageHandler() {return new MessageHandler();}
}
  • WebSocket Handshake

要定制初始的HTTP WebSocket握手请求,最简单的方法是使用HandshakeInterceptor,它提供了握手前和握手后的方法。你可以使用这样的拦截器来阻止握手,或者让 WebSocketSession可以访问任何属性。下面的例子使用内置的拦截器将HTTP会话属性传递给WebSocket会话:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(messageHandler(), "/message").setHandshakeHandler(handshakeHandler())// 添加捂手拦截器.addInterceptors(new HandshakeInterceptor() {// 如果该方法返回false,则不允许建立连接@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {// todoattributes.put("uid", uid) ;return true ;}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,Exception exception) {// todo}}) ;}
}
  • 部署

Spring WebSocket API很容易集成到Spring MVC应用程序中,DispatcherServlet可以同时处理HTTP WebSocket握手和其他HTTP请求。调用
WebSocketHttpRequestHandler也很容易集成到其他HTTP处理场景中。这样既方便又容易理解。但是,对于JSR-356运行时,需要特别注意。

Java WebSocket API (JSR-356)提供两种部署机制。第一种方法涉及启动时的Servlet容器类路径扫描(Servlet 3特性)@ServerEndpoint。另一个是Servlet容器初始化时使用的注册 API(
ServletContainerInitializer)。这两种机制都不可能对所有HTTP处理使用单个“前端控制器” — 包括WebSocket握手和所有其他HTTP请求 — 如Spring MVC的DispatcherServlet。

这是JSR-356的一个重要限制,Spring的WebSocket支持通过特定于服务器的RequestUpgradeStrategy实现来解决这个问题,即使运行在JSR-356运行时也是如此。Tomcat、Jetty、GlassFish、WebLogic、WebSphere和Undertow(以及WildFly)目前都存在这样的策略。

  • 服务配置

每个底层WebSocket引擎都公开了控制运行时特征的配置属性,例如消息缓冲区大小、空闲超时等。

对于Tomcat、WildFly和GlassFish,可以在WebSocket Java配置中添加
ServletServerContainerFactoryBean,如下面的例子所示:

@Bean
public ServletServerContainerFactoryBean servletServerContainerFactoryBean() {ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean() ;container.setMaxTextMessageBufferSize(8192) ;container.setMaxBinaryMessageBufferSize(8192) ;return container ;
}
  • 允许的来源

从Spring Framework 4.1.5开始,WebSocket和SockJS的默认行为是只接受同源请求。也可以允许所有或指定的来源列表。这个检查主要是为浏览器客户端设计的。没有什么能阻止其他类型的客户端修改Origin首部值。

三种可能的行为是:

  1. 仅允许同源请求(默认):在这种模式下,当启用SockJS时,Iframe HTTP响应头X-Frame-Options设置为SAMEORIGIN,并且禁用JSONP传输,因为它不允许检查请求的来源。因此,启用此模式时,不支持IE6和IE7。

  2. 允许指定的来源列表:每个允许的来源必须以http://或https://.开头在此模式下,当启用SockJS时,禁用IFrame传输。因此,启用此模式时,将不支持IE6到IE9。

  3. 允许所有来源:要启用此模式,你应该提供*作为允许的来源值。在该模式下,所有传输通道都可用。

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(messageHandler(), "/message").setAllowedOriginPatterns("*") ;}
}

图片

测试

通过上面的介绍和配置,WebSocket环境就算是简单的配置完成了,接下来通过Postman进行测试。

图片

连接成功

图片

发送消息及接收消息

图片

服务端接收到消息

完毕!!!

 求助三连~~~

 图片

 

相关文章:

SpringBoot整合WebSocket详解

环境&#xff1a;Springboot3.0.5 WebSocket介绍 WebSocket协议RFC 6455提供了一种标准化的方式&#xff0c;通过一个TCP连接在客户端和服务器之间建立全双工、双向的通信通道。它是一个不同于HTTP的TCP协议&#xff0c;但设计为在HTTP之上工作&#xff0c;使用80和443端口&am…...

伪原创神码ai怎么样【php源码】

这篇文章主要介绍了python汉化补丁包下载&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 火车头采集ai伪原创插件截图&#xff1a; ** Spyder汉化&#xff08;python汉化&…...

Air001基于Keil环境开发,使用airisp串口命令行烧录

Air001基于Keil环境开发&#xff0c;使用airisp串口命令行烧录 有人会有这样的疑惑&#xff0c;使用Keil平台开发&#xff0c;为什么不直接使用CMSIS-DAP直接烧录&#xff0c;还要使用串口方式来去单独烧录&#xff0c;不是我不想&#xff0c;目前使用合宙官方的Air103芯片版本…...

kubernetes 中的事件(event)简介以及如何收集event和基于event告警

引用另外一篇文章对k8s event的介绍 1.什么是kubernetes事件 Kubernetes Events 是一种 Kubernetes 资源对象&#xff0c;记录了某个组件在某个时间做了某个动作&#xff0c;用于展示集群内发生的情况&#xff0c;当 Kubernetes 集群中资源状态发生变化时&#xff0c;可以产生…...

C++小游戏贪吃蛇源码

graphics.h是针对DOS下的一个C语言图形库 (c也可以) 目前支持下载此头文件的常用的有两种: 1. EGE (Easy Graphics Engine)2. EasyX Graphics LibraryEGE, 全名Easy Graphics Engine, 是windows下的简易绘图库&#xff0c;是一个类似BGI(graphics.h)的面向C/C语言新手的图形库…...

【密码学】穴居人密码

穴居人密码 文字记载中&#xff0c;有时会把来自古希腊文化之前的各种记录作为密码学的例子&#xff0c;但称它们为密码学一定太不严格了&#xff0c;这是因为那些方法都太原始了。密码学的起源能追溯到多早&#xff0c;取决于你把密码学的相关定义确定得有多宽泛。大多数作者都…...

neo4j的CQL命令实例演示

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

vue3+ts使用antv/x6

使用 2.x 版本 x6.antv 新官网: 安装 npm install antv/x6 //"antv/x6": "^2.1.6",项目结构 1、初始化画布 index.vue <template><div id"container"></div> </template><script setup langts> import { onM…...

wsl1 ubuntu通过宿主机代理连接外网

文章目录 环境变量配置apt换源apt安装&#xff0c;测试是否能通外网可能出现的问题&#xff1a;Temporary failure resolving 参考 背景&#xff1a;公司电脑是局域网&#xff0c;通过走代理来连接外网 wsl1 ubuntu想要通过来连接宿主机的局域网代理&#xff0c;访问外网 可以…...

ubuntu20.04 opencv4.2 安装笔记

参考&#xff1a; https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html Build with opencv_contrib # 1. Install minimal prerequisites&#xff0c; libgtk2.0-dev pkg-config 用来显示图像 sudo apt update && sudo apt install -y cmake g wget un…...

ubuntu安装nginx以及php的部署

目录 1.安装依赖包 2.安装nginx 3.编译nginx 4.启动nginx 5.访问nginx 6.增加源地址 7.安装php 8.配置php-fpm 9.修改权限 10.配置nginx里的php 11.启动php-fpm 12.配置php文件以及权限 13.登陆查看 1.安装依赖包 apt-get install gcc apt-get install libpcre3 l…...

IntelliJ IDEA 2021/2022关闭双击shift全局搜索

我这里演示的是修改&#xff0c;删除是右键的时候选择Remove就好了 IDEA左上角 File-->Settings 找到Navigate -->Search Everywhere &#xff0c;右键添加快捷键。 OK --> Apply应用...

HTML 元素中的name 属性

name 属性是 HTML 元素中常用的属性之一。它用于指定表单元素的名称&#xff0c;以便在提交表单时将其值与对应的键关联起来。 每个表单元素&#xff08;例如 <input>、<select> 和 <textarea>&#xff09;都可以具有一个 name 属性&#xff0c;该属性为元素…...

快速上手React:从概述到组件与事件处理

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…...

K8S系列文章之 离线安装自动化工具Ansible

参考 文档 离线安装 Ansible - DevOps - dbaselife 一、Ansible简介 Ansible是一款开源的IT配置管理工具&#xff0c;常被IT界的小伙伴们用于自动化的场景&#xff0c;多用在服务部署、配置管理方面。配置文件采用最常见的yaml格式&#xff0c;学习起来也是比较容易&#xff…...

mysql8.0.3集群搭建

下载mysql安装包&#xff1a; https://dev.mysql.com/downloads/mysql/5.7.html#downloads 准备环境 1、准备三台服务器并设置hosts 192.168.236.143 mysql1 192.168.236.144 mysql2 192.168.236.145 mysql32、设置免密登陆 #生成秘钥 ssh-keygen -t rsa #一直按Enter即可…...

vue中router路由的原理?两种路由模式如何实现?(vue2) -(上)

平时我们编写路由时&#xff0c;通常直接下载插件使用&#xff0c;在main.js文件中引入直接通过引入vue-router中的Router通过Vue.use使用以后定义一个routeMap数组&#xff0c;里边是我们编写路由的地方&#xff0c;最后通过实例化一个 Router实例 将routes我们定义的routeMao…...

消息队列(3) -封装数据库的操作

前言 上一篇博客我们写了, 关于交换机, 队列,绑定, 写入数据库的一些建库建表的操作 这一篇博客中,我们将建库建表操作,封装一下实现层一个类来供上层服务的调用 , 并在写完该类之后, 测试代码是否完整 实现封装 在写完上述的接口类 与 xml 后, 我们想要 创建一个类 ,来调用…...

PostgreSQL中根据时间段范围查询数据,如19:29:10到20:29:10范围内的数据,排除年月日

数据格式如下 问题描述 我的SQL语句条件是 WHERE (TO_CHAR(cti.binder_gen_time, YYYY-MM-DD HH:mm:ss) > 19:29:10 AND TO_CHAR(cti.binder_gen_time, YYYY-MM-DD HH:mm:ss) < 20:29:10)为什么我数据的时间是2023-07-20 17:58:29也能被查出来&#xff1f; 问题解决…...

【二分+贪心】CF1665 C

Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a; 一开始想太简单wa6了 只想到先感染大的分量&#xff0c;然后最后把最大的分量剩下的染色 但是可能会有别的分量更大&#xff08;因为最后给最大的染色之后可能不再是最大的&#xff09; 可以用堆维护&#xf…...

2026最权威的六大AI写作助手推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能技术迅猛又快速地发展着&#xff0c;为毕业论文写作开辟出全新路径&#xff0c;AI能…...

如何快速掌握TMD Matlab潮汐工具箱:海洋研究的终极指南 [特殊字符]

如何快速掌握TMD Matlab潮汐工具箱&#xff1a;海洋研究的终极指南 &#x1f30a; 【免费下载链接】TMD_Matlab_Toolbox_v2.5 项目地址: https://gitcode.com/gh_mirrors/tm/TMD_Matlab_Toolbox_v2.5 TMD Matlab Toolbox v2.5&#xff08;潮汐模型驱动工具箱&#xff0…...

MarkDownload终极指南:5个高级技巧解决网页内容整理痛点

MarkDownload终极指南&#xff1a;5个高级技巧解决网页内容整理痛点 【免费下载链接】markdownload A Firefox and Google Chrome extension to clip websites and download them into a readable markdown file. 项目地址: https://gitcode.com/gh_mirrors/ma/markdownload …...

跨平台B站资源下载神器:BiliTools工具箱完整使用指南

跨平台B站资源下载神器&#xff1a;BiliTools工具箱完整使用指南 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools 你…...

工业级进阶版 LangGraph RAG

工业级进阶版 LangGraph RAG,彻底替换掉老旧的 RetrievalQA 链式写法,实现: 拆分检索、重排、上下文组装、LLM 回答独立节点 条件路由:无需检索直接回答 / 需要检索再走 RAG 支持上下文重排(Rerank)提升精度 完整状态管理、可扩展多轮、人工干预、故障重试 纯 LangGraph …...

如何一劳永逸解决Windows运行库依赖问题:Visual C++ Redistributable终极解决方案

如何一劳永逸解决Windows运行库依赖问题&#xff1a;Visual C Redistributable终极解决方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist Visual C Redistribu…...

智能硬件开发:利用LFM2.5-1.2B-Instruct为DHT11温湿度传感器生成数据解析逻辑

智能硬件开发&#xff1a;利用LFM2.5-1.2B-Instruct为DHT11温湿度传感器生成数据解析逻辑 1. 引言&#xff1a;物联网开发中的传感器数据处理挑战 在智能家居和工业物联网项目中&#xff0c;温湿度传感器是最基础也最常用的感知设备之一。DHT11作为经典的数字温湿度传感器&am…...

Mem Reduct终极多语言设置指南:让你的内存管理工具说你的语言

Mem Reduct终极多语言设置指南&#xff1a;让你的内存管理工具说你的语言 【免费下载链接】memreduct Lightweight real-time memory management application to monitor and clean system memory on your computer. 项目地址: https://gitcode.com/gh_mirrors/me/memreduct …...

保姆级教程:在Ubuntu18.04上,用速腾16线雷达+IMU跑通Fast-LIO2建图(附完整配置流程)

零基础实战&#xff1a;Ubuntu18.04下速腾16线雷达与IMU融合的Fast-LIO2建图全流程 第一次接触激光雷达建图时&#xff0c;我被各种驱动配置、数据格式转换和参数调试折磨得焦头烂额。直到成功运行Fast-LIO2看到地图生成的那一刻&#xff0c;才真正理解为什么说SLAM是机器人领域…...

Catala快速入门教程:如何在5分钟内将法律条文转化为算法

Catala快速入门教程&#xff1a;如何在5分钟内将法律条文转化为算法 【免费下载链接】catala Programming language for literate programming law specification 项目地址: https://gitcode.com/gh_mirrors/ca/catala Catala是一种专为法律条文编程设计的语言&#xff…...