当前位置: 首页 > 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…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...