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

websocket的使用

1.引入依赖

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

2.配置websocket服务

@Configuration
public class WebSocketConfig {/*** 配置WebSocket服务* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

3.启动类添加注解

@EnableWebSocket

4.websocket服务端逻辑

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/*** WebSocketServer服务端*/
@Slf4j
@Component
@ServerEndpoint("/websocket/{uid}")
public class WebSocketClient {/*** 静态变量,用来记录当前在线连接数,线程安全的类。*/private static AtomicInteger onlineSessionClientCount = new AtomicInteger(0);/*** 存放所有在线的客户端*/private static Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>();/*** 连接uid和连接会话*/private String uid;private Session session;/*** 连接建立成功调用的方法。由前端<code>new WebSocket</code>触发** @param uid     每次页面建立连接时传入到服务端的id,比如用户id等。可以自定义。* @param session 与某个客户端的连接会话,需要通过它来给客户端发送消息*/@OnOpenpublic void onOpen(@PathParam("uid") String uid, Session session) {/*** session.getId():当前session会话会自动生成一个id,从0开始累加的。*/log.info("连接建立中 ==> session_id = {}, sid = {}", session.getId(), uid);//加入 Map中。将页面的uid和session绑定或者session.getId()与session//onlineSessionIdClientMap.put(session.getId(), session);onlineSessionClientMap.put(uid, session);//在线数加1onlineSessionClientCount.incrementAndGet();this.uid = uid;this.session = session;sendToOne(uid, "连接成功");log.info("连接建立成功,当前在线数为:{} ==> 开始监听新连接:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);}/*** 连接关闭调用的方法。由前端<code>socket.close()</code>触发** @param uid* @param session*/@OnClosepublic void onClose(@PathParam("uid") String uid, Session session) {//onlineSessionIdClientMap.remove(session.getId());// 从 Map中移除onlineSessionClientMap.remove(uid);//在线数减1onlineSessionClientCount.decrementAndGet();log.info("连接关闭成功,当前在线数为:{} ==> 关闭该连接信息:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);}/*** 收到客户端消息后调用的方法。由前端<code>socket.send</code>触发* * 当服务端执行toSession.getAsyncRemote().sendText(xxx)后,前端的socket.onmessage得到监听。** @param message* @param session*/@OnMessagepublic void onMessage(String message, Session session) {/*** html界面传递来得数据格式,可以自定义.* {"sid":"user-1","message":"hello websocket"}*/log.info("接收到消息-----------------"+message);List<String> uids = session.getRequestParameterMap().get("uid");for (String uid : uids) {// 接收前端拖推送改的消息sendToOne(uid, "来自服务端的推送=====》你好前端! 我已经成功收到消息!消息数据为:" + message);}}/*** 发生错误调用的方法** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("WebSocket发生错误,错误信息为:" + error.getMessage());error.printStackTrace();}/*** 群发消息** @param message 消息*/public void sendToAll(String message) {// 遍历在线map集合onlineSessionClientMap.forEach((onlineSid, toSession) -> {// 排除掉自己if (!uid.equalsIgnoreCase(onlineSid)) {log.info("服务端给客户端群发消息 ==> sid = {}, toSid = {}, message = {}", uid, onlineSid, message);toSession.getAsyncRemote().sendText(message);}});}/*** 指定发送消息** @param toUid* @param message*/public boolean sendToOne(String toUid, String message) {/** 判断发送者是否在线*/Session toSession = onlineSessionClientMap.get(toUid);if (toSession == null) {log.error("服务端给客户端发送消息 ==> toSid = {} 不存在, message = {}", toUid, message);return false;}// 异步发送log.info("服务端给客户端发送消息 ==> toSid = {}, message = {}", toUid, message);toSession.getAsyncRemote().sendText(message);return true;}}

5.service层调用推送消息方法

@Service
public class WebSocketHandler {@Resourceprivate WebSocketClient webSocketClient;public boolean sendMessageOne(String userId,String content) {boolean flag = webSocketClient.sendToOne(userId,content);return flag;}
}

6.controller层逻辑

@PostMapping("/send")public Map push2(@RequestBody PushDTO pushDTO){Map map = new HashMap();//1、参数校验,非空~if(StringUtils.isEmpty(pushDTO.getMessage()) || pushDTO.getUserId() == null || pushDTO.getPushType() == null )    {log.info("【消息推送】 参数异常");map.put("code","-1");map.put("msg","参数异常");return map;}//2、推送消息boolean flag = webSocketHandler.sendMessageOne(pushMessage.getUserId() + "", content);//3、如果推送成功,修改状态,返回正确的JSONif(flag){PushMessage updatePushMessage = new PushMessage();updatePushMessage.setId(pushMessage.getId());updatePushMessage.setPushState(PUSH_SUCCESS);
//            pushMessageService.updateById(updatePushMessage);map.put("code","200");map.put("msg","成功");return map;}//4、返回用户未上线的JSONmap.put("code","500");map.put("msg","用户离线");return map;}

相关文章:

websocket的使用

1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency> 2.配置websocket服务 Configuration public class WebSocketConfig {/*** 配置WebSocket服…...

docker如何建立本地私有仓库,并将docker镜像推到私有仓库

在 Docker 中&#xff0c;您可以通过 Docker Registry 创建本地私有仓库&#xff0c;并将 Docker 镜像推送到这个私有仓库。以下是具体步骤&#xff1a; 步骤 1&#xff1a;启动一个本地 Docker 私有仓库 拉取 registry 镜像&#xff1a; Docker 官方提供了一个 registry 镜像…...

vllm启动大语言模型时指定chat_template

问题介绍 在Linux下启动vllm&#xff1a; python3 -m vllm.entrypoints.openai.api_server --host 0.0.0.0 --model /model/Baichuan2-7B-Chat --trust-remote-code --gpu-memory-utilization 0.80使用下面的命令测试出错&#xff1a; curl -X POST \http://127.0.0.1…...

网络相关(HTTP/TCP/UDP/IP)

网络相关 常见的状态码 100 临时响应 100 继续,请求者应当继续提出请求101 切换协议200 成功响应 200: 服务器成功处理请求201 以创建,请求成功并且服务器创建了新的资源202 已接受:服务器已接受请求,但尚未处理203 非授权信息:服务器已成功处理请求,但返回的信息可能来…...

TF卡长期不用会丢失数据吗?TF卡数据恢复容易吗?

在现代科技快速发展的时代&#xff0c;TF卡&#xff08;TransFlash卡&#xff09;作为便携式存储设备&#xff0c;广泛应用于手机、相机、无人机等多种电子设备中&#xff0c;成为我们日常存储照片、视频、文档等重要数据的得力助手。然而&#xff0c;关于TF卡长期不使用是否会…...

Flink状态一致性保证

前言 一个Flink作业由一系列算子构成&#xff0c;每个算子可以有多个并行实例&#xff0c;这些实例被称为 subTask&#xff0c;每个subTask运行在不同的进程或物理机上&#xff0c;以实现作业的并行处理。在这个复杂的分布式场景中&#xff0c;任何一个节点故障都有可能导致 F…...

前端一键复制解决方案分享

需求背景 用户需要对流水号进行复制使用&#xff0c;前端的展示是通过样式控制&#xff0c;超出省略号表示&#xff0c;鼠标悬浮展示完整流水号。此处的鼠标悬浮展示采用的是:title&#xff0c;这样就无法对文本进行选中。 下面是给出一键复制的不同的解决方案&#xff0c;希望…...

麒麟操作系统swap使用率过高的排查思路

现象&#xff1a;用户业务环境服务器在运行时&#xff0c;监控平台告警swap使用99%&#xff0c;在系统内查询物理内存使用39%左右&#xff0c;swap使用达99%。 问题排查&#xff1a; 1&#xff09;使用命令查询使用了swap空间的进程并排序&#xff1a;for i in cd /proc;ls |gr…...

爬虫python=豆瓣Top250电影

主流程&#xff1a;获取数据&#xff0c;解析数据&#xff0c;保存数据 from bs4 import BeautifulSoup #网页解析获取数据 import re #正则表达式 import urllib.request,urllib.error #获取网页数据 import sqlite3 #轻量级数据库 import xlwt #进行excel操作 #影视详情…...

【Eclipse系列】解决Eclipse中xxx.properties文件中文乱码问题

问题描述&#xff1a;由于eclipse对Properties资源文件的编码的默认设置是ISO-8859-1&#xff0c;所以在打开.properties文件时&#xff0c;会发现中文乱码了&#xff0c;如图&#xff1a; 解决方法&#xff1a; 1、一次生效法 右击该properties文件–>properties–>Re…...

mysql主从复制及故障修复

一、主MySQL数据库的配置 分别在三台主机&#xff08;chen2/10.110、chen3/10.120、chen4/10.130)中安装mysql数据&#xff0c;其中chen2/10.110作为主MySQL服务器&#xff0c;其余两台作为从MySQL服务器。 1、在主机上部署mysql数据库 详细的请看上一篇&#xff1a;mysql数据…...

基于springboot的网上服装购物商城系统

基于springboot的网上服装购物商城系统 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a; &#x…...

aws(学习笔记第六课) AWS的虚拟私有,共有子网以及ACL,定义公网碉堡主机子网以及varnish反向代理

aws(学习笔记第六课) AWS的虚拟私有&#xff0c;共有子网以及ACL&#xff0c;定义公网碉堡主机子网以及varnish反向代理 学习内容&#xff1a; AWS的虚拟私有&#xff0c;共有子网以及ACL定义公网碉堡主机子网&#xff0c;私有子网和共有子网以及varnish反向代理 1. AWS的虚拟…...

接口测试(三)jmeter——连接mysql数据库

一、jmeter安装jdbc 1. 下载插件包&#xff0c;mysql数据库为例&#xff0c;驱动 com.mysql.jdbc.Driver 需要下载 mysql-connector-java-5.1.7-bin.jar 插件包&#xff0c;将插件包放到 jmeter 安装目录下的 lib 目录 2. 给jmeter安装jdbc驱动 二、jmeter操作数据库 1.…...

双十一购物节有哪些好物值得入手?2024双十一好物清单合集分享

一年一度的双十一购物狂欢节即将来临&#xff0c;各大平台纷纷开启预热活动&#xff0c;伴随着品牌的疯狂折扣和满减优惠&#xff0c;众多商品即将迎来超值的价格。现在正是大家“剁手”换新装备的大好时机。作为一名深耕智能产品多年的资深达人&#xff0c;今天这期我将从不同…...

jmeter中请求参数:Parameters、Body Data的区别

使用jmeter发送请求&#xff0c;常常要伴随传递参数。有两种请求参数: Parameters, Body Data, 它们的使用方式有很大不同。 先看下get和post请求的区别。 get请求&#xff1a;顾名思义是从服务器获取资源。 post请求&#xff1a;顾名思义是往服务器提交要处理的数据。 直观…...

Docker安装ActiveMQ镜像以及通过Java生产消费activemq示例

拉取镜像 docker pull docker.io/webcenter/activemq 启动容器 docker run -d --name myactivemq -p 61616:61616 -p 8162:8161 docker.io/webcenter/activemq:latest 这样就代表启动成功了 浏览器访问 http://localhost:8162/ admin admin 开启验证 修改配置文件/opt/ac…...

迅为RK3562开发板/核心板240PIN引脚全部引出,产品升级自如

可应用于人脸跟踪、身体跟踪、视频监控、自动语音识别(ASR)、图像分类驾驶员辅助系统(ADAS)、车牌识别、物体识别等。 iTOP-3562开发板/核心板采用瑞芯微RK3562处理器&#xff0c;内部集成了四核A53Mali G52架构&#xff0c;主频2GHZ&#xff0c;内置1TOPSNPU算力&#xff0c;R…...

C++实现顺序栈和链栈操作(实验3--作业)

顺序栈 一、主要功能 实现了顺序栈&#xff08;SqStack&#xff09;的数据结构&#xff0c;并利用该数据结构进行了栈的基本操作以及数制转换的功能。 二、数据结构定义 定义了一些常量&#xff1a; MAXSIZE表示栈的最大长度为 100。OVERFLOw表示存储失败的错误码为 -2。O…...

龙兴物联一体机:设备监测的智能先锋

龙兴物联物联网一体机的崛起 龙兴物联物联网一体机在设备监测领域占据着至关重要的地位。随着科技的不断进步和各行业对设备监测需求的日益增长&#xff0c;龙兴物联物联网一体机以其卓越的性能和广泛的适用性&#xff0c;迅速崛起并成为众多企业和机构的首选。 在当今数字化时…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...