WebSocket简易聊天室实现(有详细解释)

 完整代码

Arata08/online-chat-demo

服务端:

1.编写配置类,扫描有 @ServerEndpoint 注解的 Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

解释:
@Configuration 注解表示该类是一个配置类,用于定义Spring容器中的bean。配置类可以替代传统的XML配置文件,通过Java代码来声明和管理bean。
@ServerEndpointExporter 是Spring WebSocket提供的一个类,用于自动注册使用 @ServerEndpoint 注解标注的WebSocket端点。它会扫描应用程序中的所有 @ServerEndpoint 注解的类,并将它们注册为WebSocket端点。

2.编写配置类,用于获取 HttpSession 对象

import jakarta.servlet.http.HttpSession;
import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.server.HandshakeRequest;
import jakarta.websocket.server.ServerEndpointConfig;
/*** 获取HttpSession,这样的话,ChatEndpoint类就能操作HttpSession*/
public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator {@Overridepublic void modifyHandshake(ServerEndpointConfig serverEndpointConfig, HandshakeRequest request, HandshakeResponse response) {// 获取 HttpSession 对象HttpSession httpSession = (HttpSession) request.getHttpSession();// 将 httpSession 对象保存起来,存到 ServerEndpointConfig 对象中// 在 ChatEndpoint 类的 onOpen 方法就能通过 EndpointConfig 对象获取在这里存入的数据serverEndpointConfig.getUserProperties().put(HttpSession.class.getName(), httpSession);}
}

解释:

EndpointConfig端点配置类使用-CSDN博客文章浏览阅读2次。接口位于包中,它是Java WebSocket API(JSR 356)的一部分。Spring WebSocket框架也提供了对这个接口的支持。https://blog.csdn.net/m0_61160520/article/details/143819154?fromshare=blogdetail&sharetype=blogdetail&sharerId=143819154&sharerefer=PC&sharesource=m0_61160520&sharefrom=from_link

modifyHandshake 方法在WebSocket握手过程中被调用。它允许你在握手阶段修改 ServerEndpointConfig 对象,并访问HTTP请求和响应对象。这个方法的签名如下:

public void modifyHandshake(ServerEndpointConfig serverEndpointConfig, HandshakeRequest request, HandshakeResponse response)
  • serverEndpointConfig:当前WebSocket端点的配置对象。
  • request:握手请求对象,包含客户端发起握手请求的信息。
  • response:握手响应对象,包含服务器对握手请求的响应信息。

3.注册一个WebSocket端点类

解释:https://blog.csdn.net/m0_61160520/article/details/143818152?fromshare=blogdetail&sharetype=blogdetail&sharerId=143818152&sharerefer=PC&sharesource=m0_61160520&sharefrom=from_linkicon-default.png?t=O83Ahttps://blog.csdn.net/m0_61160520/article/details/143818152?fromshare=blogdetail&sharetype=blogdetail&sharerId=143818152&sharerefer=PC&sharesource=m0_61160520&sharefrom=from_link

import cn.edu.scau.config.GetHttpSessionConfig;
import cn.edu.scau.utils.MessageUtils;
import cn.edu.scau.websocket.pojo.Message;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndpoint {// 保存在线的用户,key为用户名,value为 Session 对象private static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();private HttpSession httpSession;/*** 建立websocket连接后,被调用** @param session Session*/@OnOpenpublic void onOpen(Session session, EndpointConfig config) {this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());String user = (String) this.httpSession.getAttribute("currentUser");if (user != null) {onlineUsers.put(user, session);}// 通知所有用户,当前用户上线了String message = MessageUtils.getMessage(true, null, getFriends());broadcastAllUsers(message);}private Set<String> getFriends() {return onlineUsers.keySet();}private void broadcastAllUsers(String message) {try {Set<Map.Entry<String, Session>> entries = onlineUsers.entrySet();for (Map.Entry<String, Session> entry : entries) {// 获取到所有用户对应的 session 对象Session session = entry.getValue();// 使用 getBasicRemote() 方法发送同步消息session.getBasicRemote().sendText(message);}} catch (Exception exception) {exception.printStackTrace();}}/*** 浏览器发送消息到服务端时该方法会被调用,也就是私聊* 张三  -->  李四** @param message String*/@OnMessagepublic void onMessage(String message) {try {// 将消息推送给指定的用户Message msg = JSON.parseObject(message, Message.class);// 获取消息接收方的用户名String toName = msg.getToName();String tempMessage = msg.getMessage();// 获取消息接收方用户对象的 session 对象Session session = onlineUsers.get(toName);String currentUser = (String) this.httpSession.getAttribute("currentUser");String messageToSend = MessageUtils.getMessage(false, currentUser, tempMessage);session.getBasicRemote().sendText(messageToSend);} catch (Exception exception) {exception.printStackTrace();}}/*** 断开 websocket 连接时被调用** @param session Session*/@OnClosepublic void onClose(Session session) throws IOException {// 1.从 onlineUsers 中删除当前用户的 session 对象,表示当前用户已下线String user = (String) this.httpSession.getAttribute("currentUser");if (user != null) {Session remove = onlineUsers.remove(user);if (remove != null) {remove.close();}session.close();}// 2.通知其他用户,当前用户已下线// 注意:不是发送类似于 xxx 已下线的消息,而是向在线用户重新发送一次当前在线的所有用户String message = MessageUtils.getMessage(true, null, getFriends());broadcastAllUsers(message);}}

客户端

1.创建一个 axios 实例

向后端发送登录请求需要使用这个 axios 实例

import axios from 'axios'const request = axios.create({baseURL: '/api',timeout: 60000,headers: {'Content-Type': 'application/json;charset=UTF-8'}
})request.interceptors.request.use()request.interceptors.response.use(response => {if (response.data) {return response.data}return response
}, (error) => {return Promise.reject(error)
})export default request

2.编写代理规则

vite.config.js

import {fileURLToPath, URL} from 'node:url'import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},server: {proxy: {'/api': {target: 'http://localhost:7024',changeOrigin: true,rewrite: (path) => {return path.replace('/api', '')}}}}
})

3.创建 WebSocket 对象

webSocket.value = new WebSocket('ws://localhost:7024/chat')

4.为 WebSocket 对象绑定事件

webSocket.value.onopen = onOpen// 接收到服务端推送的消息后触发
webSocket.value.onmessage = onMessagewebSocket.value.onclose = onClose

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

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

相关文章

解决Xeyes: Error can‘t open display,远程X无法连通问题。

一、问题分析 提前申明&#xff1a; 本次实验使用REHL 8 进行操作&#xff01; 客户机 A 为X-Client &#xff0c;即远程X的客户端。 服务机 B 为X-Server&#xff0c;即远程X的服务端。 问题的所有操作均在已经配置好Xorg的前提下进行的&#xff0c;不知道不配置会有什么影响&…

19.UE5道具掉落

2-21 道具掉落&#xff0c;回血、回蓝、升级提升伤害_哔哩哔哩_bilibili 目录 1.道具的创建&#xff0c;道具功能的实现 2.随机掉落 1.道具的创建&#xff0c;道具功能的实现 新建Actor蓝图&#xff0c;并命名为道具总类&#xff0c;添加一个Niagara粒子组件和一个碰撞箱bo…

DevExpress WinForms中文教程:Data Grid - 如何绑定到实体框架数据源?

在本教程中&#xff0c;您将学习如何将DevExpress WinForms的网格控件绑定到实体框架数据源、如何使用数据注释属性来更改网格显示和管理数据的方式&#xff0c;以及如何将单元格值更改发送回数据源。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Wi…

关于强化学习的一份介绍

在这篇文章中&#xff0c;我将介绍与强化学习有关的一些东西&#xff0c;具体包括相关概念、k-摇臂机、强化学习的种类等。 一、基本概念 所谓强化学习就是去学习&#xff1a;做什么才能使得数值化的收益信号最大化。学习者不会被告知应该采取什么动作&#xff0c;而是必须通…

微服务day07

MQ高级 发送者可靠性&#xff0c;MQ的可靠性&#xff0c;消费者可靠性。 发送者可靠性 发送者重连 连接重试的配置文件&#xff1a; spring:rabbitmq:connection-timeout: 1s # 设置MQ的连接超时时间template:retry:enabled: true # 开启超时重试机制initial-interval: 10…

i春秋-EXEC(命令执行、nc传输文件、带外通道传输数据)

练习平台地址 竞赛中心 题目描述 题目内容 小猫旁边有一个no sign F12检查页面 没有提示 检查源代码 发现使用了vim编辑器 进而联想到vim编辑器的临时交换文件.xxx.swp 访问.index.php.swp&#xff0c;成功下载文件 使用vim -r 查看文件内容 vim -r index.php.swp <?p…

【Web前端】Promise的使用

Promise是异步编程的核心概念之一。代表一个可能尚未完成的操作&#xff0c;并提供了一种机制来处理该操作最终的成功或失败。具体来说&#xff0c;Promise是由异步函数返回的对象&#xff0c;能够指示该操作当前所处的状态。 当Promise被创建时&#xff0c;它会处于“待定”&a…

YOLO系列基础(六)YOLOv1原理详解,清晰明了!

系列文章地址 YOLO系列基础&#xff08;一&#xff09;卷积神经网络原理详解与基础层级结构说明-CSDN博客 YOLO系列基础&#xff08;二&#xff09;Bottleneck瓶颈层原理详解-CSDN博客 YOLO系列基础&#xff08;三&#xff09;从ResNet残差网络到C3层-CSDN博客 YOLO系列基础…

硬石电机学习2024116

F4 概况 共模抑制线圈作用是滤波 LD3.3是将5v转为芯片用的3.3V CH340用于板子和电脑通讯 光耦隔离保护主控 16M的外部flash 1M的芯片内部的flash 10kHZ高速的光耦隔离&#xff0c;1M的低俗光耦隔离 F4 stm32概况 stm8和51都是一次可以运算处理8位的 32表示一次处理32位…

基于Python爬虫大屏可视化的热门旅游景点数据分析系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

RAG经验论文《FACTS About Building Retrieval Augmented Generation-based Chatbots》笔记

《FACTS About Building Retrieval Augmented Generation-based Chatbots》是2024年7月英伟达的团队发表的基于RAG的聊天机器人构建的文章。 这篇论文在待读列表很长时间了&#xff0c;一直没有读&#xff0c;看题目以为FACTS是总结的一些事实经验&#xff0c;阅读过才发现FAC…

解析传统及深度学习目标检测方法的原理与具体应用之道

深度学习目标检测算法 常用的深度学习的目标检测算法及其原理和具体应用方法&#xff1a; R-CNN&#xff08;Region-based Convolutional Neural Networks&#xff09;系列1&#xff1a; 原理&#xff1a; 候选区域生成&#xff1a;R-CNN 首先使用传统的方法&#xff08;如 Se…

boost之property

简介 property在boost.graph中有使用&#xff0c;用于表示点属性或者边属性 结构 #mermaid-svg-56YI0wFLPH0wixrJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-56YI0wFLPH0wixrJ .error-icon{fill:#552222;}#me…

Oracle 19c PDB克隆后出现Warning: PDB altered with errors受限模式处理

在进行一次19c PDB克隆过程中&#xff0c;发现克隆结束&#xff0c;在打开后出现了报错&#xff0c;PDB变成受限模式&#xff0c;以下是分析处理过程 09:25:48 SQL> alter pluggable database test1113 open instancesall; Warning: PDB altered with errors. Elapsed: 0…

AndroidStudio-Activity的生命周期

一、Avtivity的启动和结束 从当前页面跳到新页面&#xff0c;跳转代码如下&#xff1a; startActivity(new Intent(源页面.this&#xff0c;目标页面.class))&#xff1b; 从当前页面回到上一个页面&#xff0c;相当于关闭当前页面&#xff0c;返回代码如下&#xff1a; finis…

ubuntu20.04 解决Pycharm没有写入权限,无法通过检查更新更新的问题

ubuntu20.04 解决Pycharm没有写入权限&#xff0c;无法通过检查更新更新的问题 您提供的截图显示了一个关于PyCharm更新的问题&#xff0c;其中提到了&#xff1a;“PyCharm 没有 /opt/pycharm-community-2024.1.2 的写入权限&#xff0c;请通过特权用户运行以更新。” 这表明…

云原生之运维监控实践-使用Telegraf、Prometheus与Grafana实现对InfluxDB服务的监测

背景 如果你要为应用程序构建规范或用户故事&#xff0c;那么务必先把应用程序每个组件的监控指标考虑进来&#xff0c;千万不要等到项目结束或部署之前再做这件事情。——《Prometheus监控实战》 去年写了一篇在Docker环境下部署若依微服务ruoyi-cloud项目的文章&#xff0c;当…

WinDefender Weaker

PPL Windows Vista / Server 2008引入 了受保护进程的概念&#xff0c;其目的不是保护您的数据或凭据。其最初目标是保护媒体内容并符合DRM &#xff08;数字版权管理&#xff09;要求。Microsoft开发了此机制&#xff0c;以便您的媒体播放器可以读取例如蓝光&#xff0c;同时…

计算机视觉 1-8章 (硕士)

文章目录 零、前言1.先行课程&#xff1a;python、深度学习、数字图像处理2.查文献3.环境安装 第一章&#xff1a;概论1.计算机视觉的概念2.机器学习 第二章&#xff1a;图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示&#xff1a;图像金字…