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

Spring Boot整合WebSocket

说明:本文介绍如何在Spirng Boot中整合WebSocket,WebSocket介绍,参考下面这篇文章:

  • WebSocket

原始方式

原始方式,指的是使用Spring Boot自己整合的方式,导入的是下面这个依赖

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

Step1:创建WebSocket类

创建一个WebSocket服务类,如下:

import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;/*** WebSocket服务*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {// 存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 客户端连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法** @param sid*/@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}/*** 群发** @param message*/public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}
}

Step2:注入IOC中

将WebSocketServer注入到IOC容器中,如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类,用于注册WebSocket的Bean*/
@Configuration
public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

Step3:创建任务

如下,创建一个服务器主动推送给客户端的任务,每5秒推送消息给客户端;

在这里插入代码片import com.hezy.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;@Component
public class WebSocketTask {@Autowiredprivate WebSocketServer webSocketServer;/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}
}

Step4:启动类增加注解

启动类需要增加@EnableWebSocket注解,@EnableScheduling注解是开启定时任务的,配合定时器注解@Scheduled(cron = "0/5 * * * * ?")

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.config.annotation.EnableWebSocket;/*** @author hezhongying* @create 2024/7/27 14:05*/
@SpringBootApplication
@EnableScheduling
@EnableWebSocket
public class Start {public static void main(String[] args) {SpringApplication.run(Start.class, args);}
}

Step5:启动测试

启动,使用Apifox测试,选择新建WebSocket接口
在这里插入图片描述

填上地址,端口号是8080,这一点和后面使用第三方框架不同;

在这里插入图片描述

连接成功,可以看到代码中的消息定时推送到客户端;

在这里插入图片描述

以上就是使用Spring Boot原始的方式整合WebSocket;

使用第三方框架

使用第三方框架(GitHub地址:netty-websocket-spring-boot-starter)的方式整合WebSocket非常容易,如下:

Step1:引入依赖

在pom.xml文件中,引入下面依赖

<dependency><groupId>org.yeauty</groupId><artifactId>netty-websocket-spring-boot-starter</artifactId><version>0.12.0</version>
</dependency>

Step2:创建WebSocket类

在GitHub上,把类拷贝过来,如下:

import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import org.springframework.util.MultiValueMap;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;import java.io.IOException;
import java.util.Map;@ServerEndpoint(host = "${ws.host}", port = "${ws.port}", path = "/ws")
public class MyWebSocket {@BeforeHandshakepublic void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){session.setSubprotocols("stomp");if (!"ok".equals(req)){System.out.println("Authentication failed!");session.close();}}@OnOpenpublic void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){System.out.println("new connection");System.out.println(req);}@OnClosepublic void onClose(Session session) throws IOException {System.out.println("one connection closed"); }@OnErrorpublic void onError(Session session, Throwable throwable) {throwable.printStackTrace();}@OnMessagepublic void onMessage(Session session, String message) {System.out.println(message);session.sendText("Hello Netty!");}@OnBinarypublic void onBinary(Session session, byte[] bytes) {for (byte b : bytes) {System.out.println(b);}session.sendBinary(bytes); }@OnEventpublic void onEvent(Session session, Object evt) {if (evt instanceof IdleStateEvent) {IdleStateEvent idleStateEvent = (IdleStateEvent) evt;switch (idleStateEvent.state()) {case READER_IDLE:System.out.println("read idle");break;case WRITER_IDLE:System.out.println("write idle");break;case ALL_IDLE:System.out.println("all idle");break;default:break;}}}
}

Step3:增加配置

在配置文件中,新增以下配置,表示websocket接收的主机和端口,如下:

# websocket配置
ws:host: 0.0.0.0port: 90

Step4:启动测试

启动项目,使用apifox测试

在这里插入图片描述

填上websocket服务地址和端口,记得加上一个参数req=ok,因为我们上面代码里有个判断

在这里插入图片描述

连接成功

在这里插入图片描述

Message里面写需要发送的内容,发送

在这里插入图片描述

可以看到,发送到消息成功,同时也接收到了服务端传递过来的消息,就是说此时如果代码里需要发送消息给客户端,就可以主动发送消息过来,可以基于上面的代码写自己的业务逻辑。

在这里插入图片描述

另外

其中相关注解,可以查看GitHub中的文档,我也在摸索中;

在这里插入图片描述

总结

本文介绍了Spring Boot使用WebSocket的两种方式

相关文章:

Spring Boot整合WebSocket

说明&#xff1a;本文介绍如何在Spirng Boot中整合WebSocket&#xff0c;WebSocket介绍&#xff0c;参考下面这篇文章&#xff1a; WebSocket 原始方式 原始方式&#xff0c;指的是使用Spring Boot自己整合的方式&#xff0c;导入的是下面这个依赖 <dependency><g…...

《LeetCode热题100》---<5.③普通数组篇五道>

本篇博客讲解LeetCode热题100道普通数组篇中的五道题 第五道&#xff1a;缺失的第一个正数&#xff08;困难&#xff09; 第五道&#xff1a;缺失的第一个正数&#xff08;困难&#xff09; 方法一&#xff1a;将数组视为哈希表 class Solution {public int firstMissingPosi…...

Cocos Creator文档学习记录

Cocos Creator文档学习记录 一、什么是Cocos Creator 官方文档链接&#xff1a;Hello World | Cocos Creator 百度百科&#xff1a;Cocos Creator_百度百科 Cocos Creator包括开发和调试、商业化 SDK 的集成、多平台发布、测试、上线这一整套工作流程&#xff0c;可多次的迭…...

插入数据优化 ---大批量数据插入建议使用load

一.insert优化 1.批量插入 2.手动提交事务 3.主键顺序插入 二.大批量插入数据 如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。操作如下 1.客户端连接服务端时,加入参数 --local-infine mysql --local-infine…...

【Linux】一篇总结!什么是重定向?输出重定向的作用是什么?什么又是追加重定向?

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;一篇总结&#xff01;什么是重定向&#xff1f;输出重定向的作用是什么&#xff1f;什么又是追加重定向&#xff1f; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Py…...

svn软件总成全内容

SVN软件总成 概述&#xff1a;本文为经验型文档 目录 D:\安装包\svn软件总成 的目录D:\安装包\svn软件总成\svn-base添加 的目录D:\安装包\svn软件总成\tools 的目录D:\安装包\svn软件总成\tools\sqlite-tools-win32-x86-3360000 的目录D:\安装包\svn软件总成\安装包-----bt lo…...

[激光原理与应用-118]:电源系统的接地详解:小信号的噪声干扰优化,从良好外壳接地开始

目录 一、电路的基本原理&#xff1a;电流回路 1、电流回路的基本概念 2、电流回路的特性 3、电流回路的类型 4、电流回路的应用 五、电流回路的注意事项 二、交流设备的接地 1.1 概述 1、交流工作接地的定义 2、交流工作接地的作用 3、交流工作接地的规范要求 4、…...

回测本身就是一种过度拟合?

这也许是一个絮絮叨叨的专题&#xff0c;跟大伙儿唠一唠量化相关的小问题&#xff0c;有感而发写到哪算哪&#xff0c;这是第一期&#xff0c;先唠个10块钱的~ 前段时间在某乎上看到这样一个问题『您怎么理解回测本身就是一种过度拟合&#xff1f;』 个人看来&#xff0c;回测本…...

什么是Arduino?

Arduino是一款便捷灵活、方便上手的开源电子原型平台&#xff0c;由欧洲的一个开发团队于2005年冬季开发。以下是关于Arduino的详细介绍&#xff1a; 一、基本概述 定义&#xff1a;Arduino是一个基于开放源代码的软硬件平台&#xff0c;它让电子设计更加简单快捷。通过Arduin…...

【机器学习基础】Scikit-learn主要用法

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…...

python-素数回文数的个数(赛氪OJ)

[题目描述] 求 11 到 n 之间&#xff08;包括 n&#xff09;&#xff0c;既是素数又是回文数的整数有多少个。输入&#xff1a; 一个大于 11 小于 10000 的整数 n。输出&#xff1a; 11 到 n 之间的素数回文数个数。样例输入1 23 样例输出1 1 提示&#xff1a; 回文数指左右对…...

OCC 网格化(二)-网格划分算法

目录 一、概述 二、详解 1. 线性偏转 (Linear Deflection) 2. 角偏转 (Angular Deflection) 三、示例 3.1 示例1 3.2 示例2 一、概述 在 Open CASCADE Technology (OCC) 中默认的网格划分算法BRepMesh_IncrementalMesh有两个主要的选项来定义三角剖分—线性和角偏转。 …...

pyecharts模块

PyEcharts 一个基于ECharts库的Python封装库&#xff0c;它使得开发者可以方便地在Python环境中创建交互式的图表&#xff0c;包括折线图、柱状图、饼图、地图等多种可视化效果。 优点&#xff1a; 易用性&#xff1a;PyEcharts提供了简单易懂的API&#xff0c;通过链式调用…...

深⼊理解指针(3)

1. 字符指针变量 2. 数组指针变量 3. ⼆维数组传参的本质 4. 函数指针变量 5. 函数指针数组 6. 转移表 1. 字符指针变量 在指针的类型中我们知道有⼀种指针类型为字符指针 ⼀般使⽤: char* 这两种方式都是把字符串中的首字符的地址赋值给pc。 在这串代码中 str1内容的地…...

黑马头条vue2.0项目实战(四)——首页—文章列表

目录 1. 头部导航栏 1.1 页面布局 1.2 样式调整中遇到的问题 2. 频道列表 2.1 页面布局 2.2 样式调整 2.3 展示频道列表 3. 文章列表 3.1 思路分析 3.2 使用 List 列表组件 3.3 加载文章列表数据 3.4 下拉刷新 3.5 设置上下padding固定头部和频道列表 3.6 记住列…...

UE5.4内容示例(4)UI_UMG - 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例&#xff0c;可以用此熟悉一遍UE5的功能 UI示例 UI_UMG &#xff1a;基本UMGUI_CommonUI &#xff1a;UMG多层应用UI_SlatePostBuffer UI &#xff1a;FX的示例&…...

C#实现数据采集系统-配置文件化

系统优化-配置 配置信息ip端口,还有点位信息,什么的都是直接在代码里直接写死,添加点位,修改配置,比较麻烦,每次修改都需要重新生成打包。 所以将这些配置都改成配置文件,这样只需要修改配置文件,程序无须修改,即可更新。 配置代码: 如果我们有100个采集,一个个去…...

Java面试题 -- 为什么重写equals就一定要重写hashcode方法

在回答这个问题之前我们先要了解equals与hascode方法的本质是做什么的 1. equals方法 public boolean equals(Object obj) {return (this obj);}我们可以看到equals在不重写的情况下是使用判断地址值是否相同 所以默认的 equals 的逻辑就是判断的双方是否引用了一个对象&am…...

J031_使用TCP协议支持与多个客户端同时通信

一、需求文档 使用TCP协议支持与多个客户端同时通信。 1.1 Client package com.itheima.tcp2;import java.io.DataOutputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner;public class Client {public static void main(String[] a…...

二分查找(精确查找、范围搜索)

目录 1. 二分查找概述2. 精确查找2.1 【left&#xff0c;right】2. 2 【left&#xff0c;right&#xff09; 3. 范围查找总结 1. 二分查找概述 二分查找法&#xff0c;也称为二分搜索法或折半查找法&#xff0c;是一种在有序数组中查找特定元素的搜索算法。其基本思想是&#x…...

告别混乱XML:Notepad++插件一键美化与智能纠错实战

1. 为什么我们需要XML格式化工具&#xff1f; 作为一个常年和XML打交道的开发者&#xff0c;我太清楚那种打开一个几千行XML文件时的绝望了——所有标签挤在一起&#xff0c;缩进混乱得像被猫抓过的毛线球&#xff0c;想找个节点得用CtrlF来回搜三遍。更可怕的是&#xff0c;有…...

别再只用欧氏距离了!用Python手写曼哈顿距离,搞定KNN和聚类中的特征选择难题

曼哈顿距离实战&#xff1a;用Python优化KNN与聚类算法特征选择 在机器学习项目中&#xff0c;我们常常默认使用欧氏距离作为度量标准&#xff0c;却忽略了其他距离函数的独特价值。曼哈顿距离&#xff08;Manhattan Distance&#xff09;作为L1范数的典型代表&#xff0c;在处…...

VisualCppRedist AIO 深度解析:从MSI自动化处理到系统注册表管理的完整解决方案

VisualCppRedist AIO 深度解析&#xff1a;从MSI自动化处理到系统注册表管理的完整解决方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 在Windows系统开发和…...

PEX8796实战解析:从芯片特性到PCIe扩展设计的关键考量

1. PEX8796芯片基础认知与核心特性 第一次拿到PEX8796这颗PCIe交换芯片时&#xff0c;我盯着密密麻麻的引脚图发了半小时呆。作为PLX&#xff08;现已被博通收购&#xff09;的经典产品&#xff0c;这颗芯片在工业控制、服务器扩展等领域已经默默服役了十余年。实测中发现&…...

imFile下载管理器:从入门到精通的免费全能下载解决方案

imFile下载管理器&#xff1a;从入门到精通的免费全能下载解决方案 【免费下载链接】imfile-desktop A full-featured download manager. 项目地址: https://gitcode.com/gh_mirrors/im/imfile-desktop imFile是一款功能全面的免费下载管理器&#xff0c;支持HTTP、FTP、…...

【Midjourney Gouache风格终极指南】:20年AI绘画专家亲授7大参数黄金组合与3类易踩翻车点

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Gouache风格的本质解构与AI绘画语境迁移 Gouache&#xff08;水粉画&#xff09;并非简单意义上的“不透明水彩”&#xff0c;其本质在于颜料颗粒的物理遮盖性、媒介乳化稳定性与干湿叠压响应的三重耦合…...

企业如何通过API Key管理与审计日志加强内部AI应用管控

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 企业如何通过API Key管理与审计日志加强内部AI应用管控 对于在企业内部规模化部署大模型应用的团队而言&#xff0c;如何确保资源被…...

嵌入式老C代码别重写!IAR项目混编C/C++的保姆级指南(extern “C“详解)

嵌入式老C代码别重写&#xff01;IAR项目混编C/C的保姆级指南&#xff08;extern "C"详解&#xff09; 当你在IAR Embedded Workbench中启动一个新项目&#xff0c;面对那些历经千锤百炼的C语言驱动和BSP代码&#xff0c;是否曾为"推倒重来还是继续维护"而…...

容器化技术从入门到精通:Docker与Kubernetes实战指南

1. 项目概述&#xff1a;从零到一构建容器化认知体系最近在技术社区里&#xff0c;经常看到有朋友在讨论“stephrobert/containers-training”这个项目。乍一看&#xff0c;这像是一个关于容器技术的培训或学习资料库。作为一个在云原生和容器化领域摸爬滚打了多年的从业者&…...

为什么92%的团队用错Gemini做Slides?——基于17家SaaS公司实测数据的生成效率断层分析

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Gemini生成Slides的底层机制与能力边界 Gemini 生成幻灯片&#xff08;Slides&#xff09;并非简单地将文本转为 PPT 页面&#xff0c;而是依托多模态大模型对语义结构、视觉层级与演示逻辑的联合建模。…...