WebSocket实现私信功能

WebSocket实现私信功能

引入依赖

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

配置文件 WebSocketConfig

package com.example.common;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;//表明配置文件
@Configuration 
@EnableWebSocket 
public class WebSocketConfig {/*** 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

前端Vue调用

    client = new WebSocket(`ws://localhost:8085/imserverSingle`)client.onopen = () => {console.log('websocket open')}client.onclose = () => {  // 页面刷新的时候和后台websocket服务关闭的时候console.log('websocket close')}send() {if (!this.toUser) {this.$notify.error('请选择聊天用户')return}if (client) {let message = this.getMessage('text')client.send(JSON.stringify(message))}document.getElementById('im-content').innerHTML = ''  // 清空输入框},

监听事件

    client.onmessage = (msg) => { //WebSocket 对象的事件监听器,用于处理从服务器接收到的消息。if (msg.data) { // 检查接收到的消息是否存在。let json = JSON.parse(msg.data)// json.fromuser === this.fromUserif (json.content && (json.fromuser === this.fromUser && json.touser === this.toUser)|| json.touser === this.fromUser && json.fromuser === this.toUser) {  // 说明是两者互相发消息this.messages.push(json) //放到消息队列里this.scrollToBottom()  // 滚动页面到最底部}// 加载消息数字 两者通信如果是对面发来的消息 说明当前正在两个人的通信窗口if (this.toUser === json.fromuser) {this.setUnReadNums()  // 把对方消息设为已读,更新未读消息数量} else {  //用户发给对方的// 可能是当前用户发给对方的消息,或者是其他人通信 都 加载当前用户的未读消息数量 每次监听到通信事件就更新未读记录this.loadUnReadNums()}}}

页面关闭销毁WebSocket

  // Vue实例销毁之前执行  释放资源beforeDestroy() {if (client) {client.close()}},

单聊 WebSocketSingleServer

package com.example.common;import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.example.entity.ImSingle;
import com.example.service.ImSingleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** websocket服务 - 单聊*/
@ServerEndpoint(value = "/imserverSingle")
@Component
public class WebSocketSingleServer implements InitializingBean {private static final Logger log = LoggerFactory.getLogger(WebSocketSingleServer.class);/*** 记录当前在线连接数*/public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();@ResourceImSingleService imSingleService;static ImSingleService staticImSingleService;/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session) {sessionMap.put(session.getId(), session);log.info("[onOpen] 新建连接,session={}, 当前在线人数为:{}", session.getId(), sessionMap.size());}/*** 连接关闭调用的方法*/@OnClosepublic void onClose(Session session) {sessionMap.remove(session.getId());log.info("[onClose] 有一连接关闭,session={}, 当前在线人数为:{}", session.getId(), sessionMap.size());}/*** 收到客户端消息后调用的方法* 后台收到客户端发送过来的消息* onMessage 是一个消息的中转站* 接受 浏览器端 socket.send 发送过来的 json数据** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session fromSession) {log.info("服务端收到消息:{}", message);ImSingle imSingle = JSONUtil.toBean(message, ImSingle.class);imSingle.setTime(DateUtil.now());// 存储数据到数据库staticImSingleService.add(imSingle);String jsonStr = JSONUtil.toJsonStr(imSingle);  // 处理后的消息体this.sendAllMessage(jsonStr);log.info("[onMessage] 发送消息:{}", jsonStr);}@OnErrorpublic void onError(Session session, Throwable error) {log.error("[onError] 发生错误", error);}/*** 服务端发送消息给除了自己的其他客户端*/private void sendMessage(Session fromSession, String message) {sessionMap.values().forEach(session -> {if (fromSession != session) {log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);try {session.getBasicRemote().sendText(message);} catch (IOException e) {log.error("服务端发送消息给客户端异常", e);}}});}/*** 服务端发送消息给所有客户端*/private void sendAllMessage(String message) {try {for (Session session : sessionMap.values()) {log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);session.getBasicRemote().sendText(message);}} catch (Exception e) {log.error("服务端发送消息给客户端失败", e);}}@Overridepublic void afterPropertiesSet() {staticImSingleService = imSingleService;}
}

JSON字符串处理

JSON.stringify 方法用于将 JavaScript 对象转换为 JSON 字符串。这个方法接受一个 JavaScript 对象作为参数,并返回一个表示该对象的 JSON 字符串。

JSON.parse 方法用于将 JSON 字符串转换回 JavaScript 对象。它接受一个包含 JSON 数据的字符串,并返回一个与该字符串相对应的 JavaScript 对象。

后端 JSONUtil.toJsonStr 通常是指一个用于将对象转换为 JSON 字符串的工具方法

后端 JSONUtil.toBean 通常是指一个用于将 JSON 字符串转换为对象的工具方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/653176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot的服务定位模式

一、文件解析器的例子 在开发中我们可能会解析CSV&#xff0c;JSON等文件类型&#xff0c;显然要用策略模式 我们先定义一个Parser接口 public interface Parser {void parse(String input); } Parser接口的实现类有JSONParser&#xff0c;CSVParser Component("CSV&qu…

gRPC 基本原理

基础知识 RPC的语义是远程过程调用&#xff08;Remote Procedure Call&#xff0c;RPC&#xff09;就是将一个服务调用封装在一个本地方法中&#xff0c;让调用者像使用本地方法一样调用服务&#xff0c;对其屏蔽实现细节。 RPC 会给对应的服务接口名生成一个代理类&#xff0c…

DPlayer m3u8 视频禁止下载

1. 介绍 正常的 m3u8 格式视频通过控制台是无法下载的&#xff0c;但是可以通过插件下载&#xff0c;下面介绍如何规避这个问题。 思路&#xff1a;后端生成一个一次性的密钥&#xff0c;前端放在请求头中&#xff0c;可以防止大部分插件下载。这里只说前端。 2. 实现 集成 …

[docker] 关于docker的面试题

docker命名空间&#xff1f; docker与虚拟机的区别&#xff1f; 容器虚拟机所有容器共享宿主机的内核每个虚拟机都有独立的操作系统和内核通过namespace实现资源隔离&#xff0c;通过cgroup实现限制资源的最大使用量完全隔离。每个虚拟机都有独立的硬件资源秒级启动速度分钟级…

超越 Node.js:Bun 的创新与突破

1. Bun Bun 是一个全新的 JavaScript 运行时&#xff0c;类似于 Node.js 和 Deno&#xff0c;它专注于提供出色的性能和开发者体验。Bun 的一些特点包括&#xff1a; 快速的性能&#xff1a;Bun 旨在提供高性能&#xff0c;无论是启动时间、执行速度还是安装依赖包的速度。 兼…

使用小米手机

额&#xff0c;因为很久以前的华为荣耀手机&#xff08;虽然现在不是华为了&#xff09;退役了&#xff0c;所以使用了小米手机。 文章目录 小米手机和电脑互联 小米手机和电脑互联 这里我用的ubuntu 22.04 和Redmi note 13 pro。其实开始我也没想到&#xff0c;小米居然可以直…

【3.6数据库系统】数据库备份与恢复技术

目录 1.数据备份1.1备份方式1.2备份类型 2.数据库故障与恢复 1.数据备份 1.1备份方式 △冷备份也称为静态备份&#xff0c;别是将数据库正常关闭&#xff0c;在停止状态下&#xff0c;将数据库的文件全部备份(复制)下来。 △热备份也称为动态备份&#xff0c;是利用备份软件&a…

林浩然的哲学穿越之旅:从道家“道”到柏罗丁的“太一”

林浩然的哲学穿越之旅&#xff1a;从道家“道”到柏罗丁的“太一” Lin Haoran’s Philosophical Journey Across Time: From Dao in Daoism to Plotinus’s “The One” 在这个充满奇思妙想的故事里&#xff0c;我们的主角林浩然可不是个普通的家伙。他是当代的一位哲学侦探&a…

【Java面试】redis

目录 Redis 介绍Reids常用5种数据类型一个字符串类型的值能存储最大容量是多少&#xff1f;Redis 有哪些适合的场景&#xff1f;Redis的并发竞争问题如何解决?什么是缓存穿透&#xff1f;如何避免&#xff1f;什么是缓存雪崩&#xff1f;何如避免&#xff1f;Redis 中设置过期…

Flutter开发进阶之Canvas

Flutter开发进阶之Canvas 在Flutter开发中Canvas作为一个绘制2D图形的工具&#xff0c;提供了一系列绘图方法&#xff0c;可以用来绘制各种形状、线条、文本和图像等&#xff1b; Canvas对象是作为CustomPainter的子组件进行构建的&#xff1b; void paint(Canvas canvas, Si…

(M)unity受伤反弹以及死亡动画

受伤反弹 1.在人物控制脚本中添加受伤后速度将为0&#xff0c;并添加一个反弹的力 在刷新移动时&#xff0c;需要在没有受伤的状态 public bool isHurt; public float hurtForce; private void FixedUpdate() {if(!isHurt)Move(); }public void GetHurt(Transform attacker) …

Kong工作原理 - 健康检查和断路器 - 健康检查的类型

主动健康检查 主动健康检查&#xff08;Active Health Checks&#xff09;顾名思义&#xff0c;是通过主动探测目标的健康状况来进行检查。当在上游实体中启用主动健康检查时&#xff0c;Kong会定期向上游的每个目标发送HTTP或HTTPS请求&#xff0c;以访问配置的路径。这使得K…

策略者模式-C#实现

该实例基于WPF实现&#xff0c;直接上代码&#xff0c;下面为三层架构的代码。 目录 一 Model 二 View 三 ViewModel 一 Model using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 设计模式练…

Day50 动态规划part11 123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV

Day50 动态规划part11 123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV 123. 买卖股票的最佳时机 III class Solution { public:int maxProfit(vector<int>& prices) {int length prices.size(); //dp[i][0]不操作 dp[i][1]第一次持有 dp[i][2]第一次不持…

探索元宇宙的未来:数字人对话系统 - Linly-Talker —— “数字人交互,与虚拟的自己互动”

探索元宇宙的未来&#xff1a;数字人对话系统 - Linly-Talker —— “数字人交互&#xff0c;与虚拟的自己互动” 之前空闲的时候我似乎已经写过了有关于数字人的两篇文章&#xff0c;今天更多的写这篇文章就是想探索一下元宇宙的未来&#xff0c;这种数字人对话系统能做什么&…

Unity - gamma space下还原linear space效果

文章目录 环境目的环境问题实践结果处理要点处理细节【OnPostProcessTexture 实现 sRGB 2 Linear 编码】 - 预处理【封装个简单的 *.cginc】 - shader runtime【shader需要gamma space下还原记得 #define _RECOVERY_LINEAR_IN_GAMMA】【颜色参数应用前 和 颜色贴图采样后】【灯…

【UE5】如何给人物骨骼绑定Control Rig用来制作动画(控制)

本篇文章暂时只教绑定人物手部的Control Rig&#xff0c;脚的Control Rig举一反三即可 1&#xff0c;右键-创建-控制绑定 2在控制绑定中-右键创建基本IK 3&#xff0c;填入上臂-下臂-手 4【手和下臂】右键-新建-Add Controls For Selected&#xff0c;&#xff08;或者新建-…

第十四章 RabbitMQ应用

文章目录 前言1、RabbitMQ概念1.1、生产者和消费者1.2、队列1.3、交换机、路由键、绑定1.3.1、交换机类型 2、RabbitMQ运转流程2.1、生产者发送消息流程2.2、消费者接收消息的过程2.3、AMQP协议 3、RabbitMQ windows安装3.1、下载3.2、安装 4、Spring Boot 整合RabbitMQ4.1、在…

[USACO22JAN] Tests for Haybales G

Farmer John 的奶牛们决定为 Farmer Nhoj 农场的奶牛们举办一场编程竞赛。为了使问题尽可能有趣&#xff0c;他们花费了大量时间来构造具有挑战性的测试用例。特别是对于一个问题&#xff0c;「Haybales」&#xff0c;奶牛们需要你的帮助来设计具有挑战性的测试用例。这有关解决…

【语录】岁月

中年 写中年&#xff0c;应该是年少励志三千里 踌躇百步无寸功&#xff0c;转眼高堂已白发 儿女蹒跚学堂中&#xff0c;不如意事常八九&#xff0c;可与人言无二三 可是诸位&#xff0c;不用悲伤&#xff0c;稻盛和夫说&#xff0c; 人生并不是一场物质的盛宴&#xff0c;而是…