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

SpringBoot——使用WebSocket功能

springboot自带websocket,通过几个简单的注解就可以实现websocket的功能;

启动类跟普通的springboot一样:

/*** 2023年3月2日下午4:16:57*/
package testspringboot.test7websocket;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;/*** @author XWF**/
@SpringBootApplication
@PropertySource(value = "test7.properties")
public class Test7Main {/*** @param args*/public static void main(String[] args) {SpringApplication.run(Test7Main.class, args);}}

还需要一个websocket的配置类:

/*** 2023年3月2日下午4:26:15*/
package testspringboot.test7websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @author XWF**/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

配置文件里只配置了一个端口:

主要的逻辑都放到@ServerEndpoint标签注释的类里,类似controller的功能;

可以使用4种注解处理业务:

  • @OnOpen:处理客户端的连接;
  • @OnClose:处理客户端断开;
  • @OnError:处理故障错误;
  • @OnMessage:处理具体消息,有三种消息类型:String类型,ByteBuffer类型,PongMessage类型,同一消息类型类里不能出现多次;

另外可以通过Session对象设置属性或者发送数据,session.getUserProperties()存取属性,session.getBasicRemote()或者session.getAsyncRemote()可以进行同步异步发送数据;

处理类:

/*** 2023年3月2日下午4:27:01*/
package testspringboot.test7websocket;import java.io.IOException;
import java.nio.ByteBuffer;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;import org.springframework.stereotype.Component;/*** @author XWF**/
@Component
@ServerEndpoint(value = "/websockettest/{name}")
public class WebSocketHandler {@OnOpen  public void onOpen(@PathParam("name") String name, Session session) throws IOException {  System.out.println("onOpen:" + name);session.getUserProperties().put("name", name);}@OnClose  public void onClose(@PathParam("name") String name, Session session) throws IOException {System.out.println("onClose:" + name);System.out.println(session.getUserProperties().get("name") + "关闭了");}@OnError  public void onError(Session session, Throwable error) {System.out.println("onERROR");error.printStackTrace();  }@OnMessagepublic void textMessage(Session session, String msg) {System.out.println("收到:" + msg);try {session.getBasicRemote().sendText("hello");} catch (IOException e) {e.printStackTrace();}}@OnMessagepublic void binaryMessage(Session session, ByteBuffer msg) {System.out.println("Binary message: " + msg.toString());}@OnMessagepublic void pongMessage(Session session, PongMessage msg) {System.out.println("Pong message: " + msg.getApplicationData().toString());}}

测试websocket用的Apipost:

连接测试:

发送数据测试:

断开连接:

另外,也可以设置自己的编解码处理自己的消息,实现javax.websocket.Encoder.Text或者javax.websocket.Encoder.Binary接口实现编码器,实现javax.websocket.Decoder.Text或者javax.websocket.Decoder.Binary接口实现解码器,解码器最多两个,一个解码Text一个Binary;

在@ServerEndpoint注解里配置上自己的encoders和decoders就可以实现自定义编解码了;

自定义消息MsgA:

/*** 2023年3月3日下午3:12:47*/
package testspringboot.test7websocket;/*** @author XWF**/
public class MsgA {public int id;public String name;@Overridepublic String toString() {return "MsgA [id=" + id + ", name=" + name + "]";}}

编码器:

/*** 2023年3月3日下午3:14:02*/
package testspringboot.test7websocket;import javax.websocket.EncodeException;
import javax.websocket.Encoder.Text;
import javax.websocket.EndpointConfig;/*** @author XWF**/
public class MsgATextEncoder implements Text<MsgA>{@Overridepublic void init(EndpointConfig endpointConfig) {System.out.println("msga encoder init");}@Overridepublic void destroy() {System.out.println("msga encoder destroy");}// 进行编码操作,将对象编码成string@Overridepublic String encode(MsgA object) throws EncodeException {return object.toString();}}

解码器:

/*** 2023年3月3日下午3:16:52*/
package testspringboot.test7websocket;import javax.websocket.DecodeException;
import javax.websocket.Decoder.Text;
import javax.websocket.EndpointConfig;/*** @author XWF**/
public class MsgATextDecoder implements Text<MsgA> {@Overridepublic void init(EndpointConfig endpointConfig) {System.out.println("msga decoder init");}@Overridepublic void destroy() {System.out.println("msga decoder destroy");}// 进行解码操作,将string解码成需要的对象@Overridepublic MsgA decode(String s) throws DecodeException {MsgA msga = new MsgA();msga.id = Integer.parseInt(s.split(",")[0]);msga.name = s.split(",")[1];return msga;}// 验证消息是否可以解码,返回true可以解码,否则返回false@Overridepublic boolean willDecode(String s) {// 接收格式:id,nameif (s.split(",").length == 2) {try {Integer.parseInt(s.split(",")[0]);} catch (NumberFormatException e) {return false;}return true;} else {return false;}}}

处理类:

/*** 2023年3月3日下午3:07:45*/
package testspringboot.test7websocket;import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;import org.springframework.stereotype.Component;/*** @author XWF**/
@Component
@ServerEndpoint(value = "/websocketmsgtest", encoders = {MsgATextEncoder.class}, decoders = {MsgATextDecoder.class})
public class WebSocketMsgHandler {@OnOpenpublic void onOpen() {}@OnClosepublic void onClose() {}@OnErrorpublic void onError(Throwable error) {}@OnMessagepublic void textMessageA(Session session, MsgA msga) {System.out.println("收到:" + msga);MsgA sendMsg = new MsgA();sendMsg.id = 9999;sendMsg.name = "HELLO WORLD";try {session.getBasicRemote().sendObject(sendMsg);} catch (IOException e) {e.printStackTrace();} catch (EncodeException e) {e.printStackTrace();}sendMsg.id = 8888;sendMsg.name = "hello world";Future<Void> future = session.getAsyncRemote().sendObject(sendMsg);try {future.get(3, TimeUnit.SECONDS);System.out.println("发送完毕");} catch (InterruptedException | ExecutionException | TimeoutException e) {System.out.println("超时");e.printStackTrace();}}}

测试:

不按照解码格式要求请求会异常并断开连接:

正常测试:

相关文章:

SpringBoot——使用WebSocket功能

springboot自带websocket&#xff0c;通过几个简单的注解就可以实现websocket的功能&#xff1b; 启动类跟普通的springboot一样&#xff1a; /*** 2023年3月2日下午4:16:57*/ package testspringboot.test7websocket;import org.springframework.boot.SpringApplication; im…...

博弈论小课堂:非零和博弈(实现双赢)【纳什均衡点】

文章目录 引言I 非零和博弈1.1 囚徒问题1.2 博弈中双方的收益矩阵II 在现实中找均衡点2.1 博弈通常不是一次性的,而是反复进行的2.2 博弈论讲的都是阳谋的策略2.3 人类还处于文明的初级阶段,人的道德水准不容高估2.4 乌合之众效应2.5 很多时候看似是双赢,其实是在更大范围内…...

数组中的逆序对

解题思路1&#xff1a; 看到这个题目&#xff0c;我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候&#xff0c;逐个比较该数字和它后面的数字的大小。如果后面的数字比它小&#xff0c;则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…...

C++基础了解-01-基础语法

基础语法 一、基础语法 C 程序可以定义为对象的集合&#xff0c;这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象&#xff0c;方法、即时变量。 对象 - 对象具有状态和行为。例如&#xff1a;一只狗的状态 - 颜色、名称、品种&#xff0c;行为 -…...

phpmyadmin 文件包含(CVE-2014-8959)

0x01 漏洞介绍 phpMyAdmin是phpMyAdmin团队开发的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库,创建、删除、修改数据库表,执行SQL脚本命令等。phpMyAdmin的GIS编辑器中libraries/gis/GIS_Factory.class.php脚本存在目录遍历漏洞。远程攻击者可借助…...

SpringBoot集成MyBatis

目录 实现步骤 1. 在项目的 pom.xml 配置文件中引入如下依赖 2. 在项目的 application.properties 配置文件中添加如下依赖 3. 新建 UserMapper.class 接口类&#xff0c;添加如下 3 个方法 4. 在 /resources/mybatis/mapper 路径(需要手动创建文件夹)下创建 UserMapper.xm…...

MySQL-索引

索引介绍索引是对数据库表中一列或者多列的值进行排序的一种结构&#xff0c;使用索引可提高数据库中特定数据的查询速度。索引是一个单独的、存储在磁盘上的数据库结构&#xff0c;它们包含着对数据表里所有记录的引用指针。使用索引用于快速找出在某个或多个列中有一特定值得…...

【STM32存储器映射-寄存器基地址-偏移】

前言 在学习STM32的时候&#xff0c;我们看到很多的寄存器编程&#xff0c; 比方说LED灯&#xff1a; //GPIOB.5端口输出高电平GPIOB->ODR|1<<5; //PB.5 输出高GPIOE->ODR|1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 …...

【华为OD机试2023】最多颜色的车辆 C++ Java Python

【华为OD机试2023】最多颜色的车辆 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收…...

特斯拉后端面试(部分)

HR告知如果面试通过要转.net-_- round1 有没有用过Java新版本&#xff0c;知道有哪些特性吗&#xff1f;A&#xff1a;没有。Q&#xff1a;我们基本在用JDK11&#xff0c;有的新项目用到JDK17了。参考答案1&#xff1a; ZGC: A Scalable Low-Latency Garbage Collector Epsi…...

【python】使用python将360个文件夹里的照片,全部复制到指定的文件夹中,并且按照顺序重新命名

最近要做一个图像生成的课题&#xff0c;在网上找了一个混合的数据集。这个数据集中一共有360个文件夹&#xff0c;然后文件夹中有6-9张不等的照片&#xff0c;我的目标就是编写python代码将所有的照片取出来&#xff0c;放到一个指定的文件夹里&#xff0c;并且从1开始按照顺序…...

【C语言】3天速刷C语言(初识)

【声明】本篇博客只用于对与刚学习C语言的同学的一个初始了解&#xff0c;具体内容请继续关注本专栏后续内容。什么是C语言C语言是一门通用计算机编程语言&#xff0c;广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及…...

如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!

概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...

云计算生态该怎么做?阿里云计算巢打了个样

2023 年 2 月 23 日至 24 日&#xff0c;由阿里云主办的「阿里云计算巢加速器」于杭州阿里云谷园区集结。 阿里云计算巢加速器于 2022 年 8 月正式启动招募&#xff0c;最终百奥利盟、极智嘉、EMQ、KodeRover、MemVerge 等 30 家创新企业入选计算加速器&#xff0c;覆盖了人工智…...

小樽C++ 多章⑧ (贰) 指针与数组

目录 1.C中数组变量名某些情况可以看成是指针 2.C语言的scanf 输入语句&#xff0c;printf 输出语句 3.用指针来当动态数组 小樽C 多章⑧ (壹) 指针变量https://blog.csdn.net/weixin_44775255/article/details/129031168 小樽C 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...

MXNet的机器翻译实践《编码器-解码器(seq2seq)和注意力机制》

机器翻译就是将一种语言翻译成另外一种语言&#xff0c;输入和输出的长度都是不定长的&#xff0c;所以这里会主要介绍两种应用&#xff0c;编码器-解码器以及注意力机制。编码器是用来分析输入序列&#xff0c;解码器用来生成输出序列。其中在训练时&#xff0c;我们会使用一些…...

RK3588平台开发系列讲解(同步与互斥篇)自旋锁介绍

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、自旋锁介绍二、自旋锁相关的函数1、普通场景2、进程上下文和下半部3、中断相关三、相关结构体四、函数实现1、初始化2、获取自旋锁沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇介绍自旋锁的使用和基…...

Linux系统CPU占用率较高问题排查思路

作为工程师&#xff0c;在日常工作中我们会遇到 Linux服务器上出现CPU负载达到100%居高不下的情况&#xff0c;如果CPU 持续跑高&#xff0c;则会影响业务系统的正常运行&#xff0c;带来企业损失。对于CPU过载问题通常使用以下两种方式即可快速定位&#xff1a;方法一第一步&a…...

源码解析——HashMap

源码解析——HashMap1. 什么 是HashMap2. 为什么要使用HashMap3. HashMap的使用4. 源码解析4.1 关键问题4.1 存储结构4.2 HashMap 的容量和负载因子4.3 初始化过程4.3 put() 方法实现原理4.3.1 hash()4.3.2 resize()4.4 get() 方法实现原理5. 面试题总结6. ConcurrentHashmap(J…...

Elasticsearch 核心技术(六):内置的 8 种分词器详解 + 代码示例

❤️ 博客主页&#xff1a;水滴技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; &#x1f338; 订阅专栏&#xff1a;大数据核心技术从入门到精通 文章目录一、内置分词器1. Standard&#xff08;标准分词器&#xff09;英文示例中文示例…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

当下AI智能硬件方案浅谈

背景&#xff1a; 现在大模型出来以后&#xff0c;打破了常规的机械式的对话&#xff0c;人机对话变得更聪明一点。 对话用到的技术主要是实时音视频&#xff0c;简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术&#xff0c;开发自己的大模型。商用方案多见为字节、百…...

开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例

在工业自动化控制系统中&#xff0c;常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中&#xff0c;客户现场采用了 罗克韦尔PLC&#xff0c;但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控&#xff0c;引入了开疆智能Etherne…...

【Java基础】​​向上转型(Upcasting)和向下转型(Downcasting)

在面向对象编程中&#xff0c;转型&#xff08;Casting&#xff09; 是指改变对象的引用类型&#xff0c;主要涉及 继承关系 和 多态。 向上转型&#xff08;Upcasting&#xff09; ⬆️ 定义 将 子类对象 赋值给 父类引用&#xff08;自动完成&#xff0c;无需强制转换&…...

Linux——TCP和UDP

一、TCP协议 1.特点 TCP提供的是面向连接、可靠的、字节流服务。 2.编程流程 &#xff08;1&#xff09;服务器端的编程流程 ①socket() 方法创建套接字 ②bind()方法指定套接字使用的IP地址和端口。 ③listen()方法用来创建监听队列。 ④accept()方法处理客户端的连接…...

大语言模型解析

1. Input Embedding embedding&#xff1a;将自然语言翻译成index 每个index对应一个embedding&#xff0c;embedding需要训练&#xff0c;embedding是一个数组...

DJango知识-模型类

一.项目创建 在想要将项目创键的目录下,输入cmd (进入命令提示符)在cmd中输入:Django-admin startproject 项目名称 (创建项目)cd 项目名称 (进入项目)Django-admin startapp 程序名称 (创建程序)python manage.py runserver 8080 (运行程序)将弹出的网址复制到浏览器中…...