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

Websocket升级版

之前写过一个关于websocket的博客,是看书时候做的一个demo。但是纸上得来终觉浅,这次实战后实打实的踩了不少坑,写个博客记录总结。

1.安装postman

websocket接口调试,需要8.5以及以上版本的postman

先把以前的卸载,直接exe安装就好

点击这个连接可以下载,或者去官网下载

https://download.csdn.net/download/qq_35653822/88419296

2.postman调试方法

2.1参考这个博客的postman调试方法

Postman进行Websocket接口测试_postman websocket-CSDN博客

2.2请求路径

不是http开头  而是ws开头

如 ws://127.0.0.1:9999/test/3

2.3测试方式

websocket接口和普通接口不同,需要先建立连接,再发送消息

建立连接时候这个url可以是pathvariable那种

如 /test/{id}

3.上代码

3.1controller层

1.@ServerEndpoint
这个注解算是websocket中极其重要的一个注解了
这里边要配置上前后端建立连接的url,后端返回前端内容的解析器。我这写了两个分别对应字符串和指定实体的解析器。以及websocket对应的config文件

2. @OnOpen  @OnMessage

@OnOpen 前后端建立连接时走的方法,也就是postman点击connect按钮时候会走的方法

@OnMessage 前端给后端发送消息时走的方法,也就是postman点击send的时候会走的方法

3.session.getBasicRemote().sendObject();

后端给前端发送消息,此处根据类型不同,走不同的解析器。也就是@ServerEndpoint中的

encoders

4.注入bean

根据idea提示,需要用set方法注入 

package websocket;import com.fasterxml.jackson.databind.ObjectMapper;
import com.valley.common.result.Result;
import com.valley.system.enums.LinkType;
import com.valley.system.pojo.bo.ConnectResultBO;
import com.valley.system.pojo.form.SourceForm;
import com.valley.system.service.SysDataSourceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.security.Principal;/*** @Description: websocket  url中得sourceId是为了指定websocket得连接*/@ServerEndpoint(value = "/linkTest/{sourceId}", encoders = {ServerEncoder.class,StringEncoder.class},configurator = WebSocketConfig.class)
@Component
@Slf4j
public class WebSocketController {private static SysDataSourceService sysDataSourceService;@Autowiredpublic void setDeviceListenerService(SysDataSourceService sysDataSourceService) {WebSocketController.sysDataSourceService = sysDataSourceService;}/*** 实现服务器主动推送*/public void sendMessage(String message, Session session) throws IOException {session.getBasicRemote().sendText(message);}/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sourceId") String sourceId) throws EncodeException, IOException {log.info("连接成功,sourceId:{}", sourceId);session.getBasicRemote().sendObject(sourceId);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) throws Exception {log.info("【websocket消息】收到客户端发来的消息:{}", message);// 创建ObjectMapper对象ObjectMapper objectMapper = new ObjectMapper();// 将JSON字符串解析为JSON对象SourceForm sourceForm = objectMapper.readValue(message, SourceForm.class);//根据type判断是否是心跳连接if(LinkType.HEARTBEAT.equals(sourceForm.getLinkType())){//前端约定返回“pong”session.getBasicRemote().sendObject("pong");return;}ConnectResultBO bo = sysDataSourceService.linkTest(sourceForm);try {Result<ConnectResultBO> result = Result.success(bo);session.getBasicRemote().sendObject(result);//session.getBasicRemote().sendText(message.toString());} catch (IOException e) {e.printStackTrace();}}}

3.2config层

1.需要配置在controller层的@ServerEndpoint中

@ServerEndpoint(value = "/api/v1/source/linkTest/{sourceId}", encoders = {ServerEncoder.class,StringEncoder.class},configurator = WebSocketConfig.class)

2. @Configuration修饰

因为要返回其他的bean

3.websocket的token上传返回

需要取header中的 Sec-WebSocket-Protocol 属性,并且返回给前端的时候也要在header中携带

package websocket;import cn.hutool.core.lang.Assert;
import com.valley.system.config.Constant;
import jodd.util.StringUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.Collections;
import java.util.List;
import java.util.Map;/*** @Description: websocket配置*/
@Configuration
public class WebSocketConfig extends ServerEndpointConfig.Configurator{@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}/*** 建立握手时,连接前的操作*/@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {// 这个userProperties 可以通过 session.getUserProperties()获取//获取请求头String token = request.getHeaders().get("Sec-WebSocket-Protocol").get(0);Assert.notNull(token,"token不可为空");//todo 之后需要对token进行解析校验//OAuth2AccessToken accessToken = tokenStore.readAccessToken(token);//前端会把空格传成&nbsp//token = token.replace(Constant.NBSP," ");//当Sec-WebSocket-Protocol请求头不为空时,需要返回给前端相同的响应response.getHeaders().put("Sec-WebSocket-Protocol", Collections.singletonList(token));super.modifyHandshake(sec, request, response);}/*** 初始化端点对象,也就是被@ServerEndpoint所标注的对象*/@Overridepublic <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {return super.getEndpointInstance(clazz);}
}

3.3解析器

1.如果不配置,在调用

session.getBasicRemote().sendObject(sourceId);

返回方法的时候会报此类型解析器不存在的错误

2.解析器写完之后要加到controller层的@ServerEndpoint中

@ServerEndpoint(value = "/api/v1/source/linkTest/{sourceId}", encoders = {ServerEncoder.class,StringEncoder.class},configurator = WebSocketConfig.class)

3.3.1实体解析器

package websocket;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.valley.common.result.Result;
import com.valley.system.pojo.bo.ConnectResultBO;import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;/*** @Description: websocket发送给前端 泛型中Result<ConnectResultBO>是要发送的类型*/
public class ServerEncoder implements Encoder.Text<Result<ConnectResultBO>> {@Overridepublic void destroy() {// TODO Auto-generated method stub// 这里不重要}@Overridepublic void init(EndpointConfig arg0) {// TODO Auto-generated method stub// 这里也不重要}@Overridepublic String encode(Result<ConnectResultBO> responseMessage) {try {JsonMapper jsonMapper = new JsonMapper();return jsonMapper.writeValueAsString(responseMessage);} catch (JsonProcessingException e) {e.printStackTrace();return null;}}
}

 3.3.2字符串解析器

现在复盘来看,我这个解析器写的完全没必要,如果要发送字符串  把

session.getBasicRemote().sendObject

改为

session.getBasicRemote().sendText

就行了

public class StringEncoder implements Encoder.Text<String>{@Overridepublic String encode(String s){return s;}@Overridepublic void init(EndpointConfig endpointConfig) {}@Overridepublic void destroy() {}
}

4.security权限过滤

这块踩了很久的坑,我们项目是开源项目改的,然后自己拆成了好几个微服务。我开始的时候只专注去改auth项目中的,不管是忽略路径permitall,还是加切面,还是加filter。都不生效。

最后,在公共项目common中找到一个关于security的配置,改了permitall,才生效

但是还要注意哈,既然在这里把权限放开了,那在config中,就得把权限校验加上

此处放开是因为,上边说过前端只能把token放到header的Sec-WebSocket-Protocol属性中,而不能像平时一样放到Authorization属性中。

 5.插曲

在进行实体转换的时候,前端多给我传了参数,引起了报错

objectMapper.readValue(message, SourceForm.class);

为了让代码健壮一点,给实体加了个注解

@JsonIgnoreProperties(ignoreUnknown = true)

Unrecognized field , not marked as ignorable解决办法-CSDN博客

相关文章:

Websocket升级版

之前写过一个关于websocket的博客&#xff0c;是看书时候做的一个demo。但是纸上得来终觉浅&#xff0c;这次实战后实打实的踩了不少坑&#xff0c;写个博客记录总结。 1.安装postman websocket接口调试&#xff0c;需要8.5以及以上版本的postman 先把以前的卸载&#xff0c…...

基于音频SOC开发板的主动降噪ANC算法源码实现

基于音频SOC开发板的主动降噪ANC算法源码实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群附加赠送降噪开发资料,...

【Pytorch】深度学习之损失函数

文章目录 二分类交叉熵损失函数交叉熵损失函数L1损失函数MSE损失函数平滑L1(Smooth L1)损失函数目标泊松分布的负对数似然损失KL散度MarginRankingLoss多标签边界损失函数二分类损失函数多分类的折页损失三元组损失HingEmbeddingLoss余弦相似度CTC损失函数参考资料 学习目标&am…...

3.4 构造方法

思维导图&#xff1a; 3.4.1 定义构造方法 ### Java中的构造方法 #### **定义与目的** 构造方法&#xff0c;也称为构造器&#xff0c;是一个特殊的成员方法&#xff0c;用于在实例化对象时为对象赋值或执行初始化操作。其主要目的是确保对象在被创建时具有有效和合适的初始状…...

代码随想录

前言 代码随想录算法训练营day43 一、Leetcode 1049. 最后一块石头的重量 II 1.题目 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分…...

2核4G游戏服务器推荐(阿里云/腾讯云/华为云)

2核4G游戏服务器推荐&#xff0c;首选腾讯云2核4G5M带宽轻量应用服务器218元一年、阿里云2核4G4M带宽轻量应用服务器297元一年&#xff0c;华为云2核2G3M云耀L服务器95元一年&#xff0c;阿腾云来详细说下2核4G游戏服务器推荐配置大全&#xff1a; 目录 2核4G游戏服务器推荐 …...

SQL标识列实现自动编号的步骤和技巧以及优势

目录 前言: 过程: 1.步骤: 2.标识种子和表示增量: 效果展示:​ 优势: 总结: 前言: 在.NET中的例子里面遇到这么一个问题&#xff0c;不能将NULL插入列‘ID’&#xff0c;表Login.dbo.Scores’;列不允许有NULL值。INSERT失败。这个问题很明显&#xff0c;我在SQL数据库中…...

【Debian】报错:su: Authentication failure

项目场景&#xff1a; 今天我重新刷了一个debian系统。 系统版本&#xff1a; # 查看系统版本 lsb_release -a 我的系统版本&#xff1a; No LSB modules are available. Distributor ID&#xff1a;Debian Description: Debian GNU/Linux 12 &#xff08;bookworm&#xff…...

我测试用的mark down教程

Markdown 教程 欢迎使用 Markdown 你好,Markdown是一种类似 Word 的排版工具,你需要仔细阅读这篇文章,了解一下 Markdown 基础知识。 Markdown 功能和列表演示 Markdown 有以下功能,帮助你用它写博客: 数学公式代码高亮导航功能等等Markdown 的优点: 间接高效大厂支持…...

网络编程基础知识总结——IP,端口,协议

目录 1. 什么是网络编程&#xff1f; 2. 网络编程的三要素 3. IP 3.1 IP地址的概念 3.2 IP地址的分类 3.3 IPv4解析 3.4 Ipv6解析 4. IPv4 的使用细节 5. 特殊IP地址 4. 端口号 5. 协议 5.1 UDP协议 5.2 TCP协议 1. 什么是网络编程&#xff1f; 总的来说就是一句…...

【LeetCode力扣】297. 二叉树的序列化与反序列化

目录 1、题目介绍 2、解题思路 2.1、详细过程图解 2.2、代码描述 2.3、完整代码 1、题目介绍 原题链接&#xff1a;297. 二叉树的序列化与反序列化 - 力扣&#xff08;LeetCode&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,null,4,5] 输出&#…...

Linux寄存器+Linux2.6内核进程调度队列+命令行参数+环境变量

目录 一、寄存器 二、Linux2.6内核进程调度队列 &#xff08;一&#xff09;优先级 &#xff08;二&#xff09;活动队列 &#xff08;三&#xff09;过期队列 &#xff08;四&#xff09;active指针和expired指针 三、命令行参数 &#xff08;一&#xff09;举例一 &…...

组合数(2)获取C(n,k)组合数列表的QT实现

1)工程文件 QT coreCONFIG c17 cmdline# You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 # disables all the APIs deprecated before Qt 6.…...

SparkCore编程RDD

RDD概述 中文名为弹性分布式数据集&#xff0c;是数据处理基本单位。代表一个弹性的&#xff0c;不可变&#xff0c;可分区&#xff0c;里面的数据可并行计算的集合。 RDD和Hadoop MR 的区别&#xff1a; RDD是先明确数据处理流程&#xff0c;数据在行动算子执行前实际上并未…...

VBA技术资料MF69:添加和删除工作表中的分页符

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…...

数字技术助力智慧公厕,让公厕变身为全新创新应用

在如今数字化的时代&#xff0c;数字技术的集成应用已经渗透到了生活的方方面面。其中一个令人瞩目的领域就是智慧公厕。以前只是简单的厕所&#xff0c;如今借助数字技术的力量&#xff0c;智慧公厕变得功能强大、智能高效。接下来&#xff0c;我们将以智慧公厕源头领航厂家广…...

electron 升级 v22 遇到问题

Electron 漏洞 https://mp.weixin.qq.com/s/5LpSJb_5uV8EIDOl3fz9Tw 由于 23以上不在支持win 7 8 8.1 所以我选择安装 v22.3.24 electron 22.3.24 node-sass 6.0.1 sass-loader 10.4.1 对应的版本 npm i node-sass6.0.1 --sass_binary_sitehttps://npm.taobao.org/mirrors…...

跟我学c++中级篇——Pimpl

一、前向声明 前向声明或者前置声明(forward declaration)&#xff0c;这个在c中用得还是比较多的。一般的框架或者库中&#xff0c;经常可以看到在一个类的前面声明了一个类&#xff0c;类似下面这样&#xff1a; class useclass; class mycall{...useclass *us; };前向声明…...

[补题记录] Atcoder Beginner Contest 295(E)

URL&#xff1a;https://atcoder.jp/contests/abc295 目录 E Problem/题意 Thought/思路 Code/代码 E Problem/题意 给定长度为 N 的数组 A。进行如下操作&#xff1a; 若 Ai 0&#xff0c;将 Ai 等概率地变为 1 ~ M 中的任意一个数&#xff1b;对 A 排序&#xff1b; …...

解决git在window11操作很慢,占用很大cpu的问题

【git在window11操作很慢&#xff0c;占用很大cpu&#xff0c;最后也执行失败】 在谷歌输入&#xff1a;git very slow in window 11。通过下面链接终于找到了解决方案&#xff1a; https://www.reddit.com/r/vscode/comments/sulebx/slow_git_in_wsl_after_updating_to_window…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

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…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...