vue+websocket实现即时聊天平台

目录

1 什么是websocket

2 实现步骤

2.1 导入依赖

2.2 编写代码


1 什么是websocket

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它主要用于在客户端和服务器之间建立持久的连接,允许实时数据交换。WebSocket 的设计目的是为了提高 Web 应用程序的交互性,减少延迟和带宽的使用。

  • 全双工通信:客户端和服务器可以同时发送和接收数据,而不需要等待对方完成发送。

  • 持久连接:建立一次连接后,可以保持该连接,直到主动关闭。这比传统的 HTTP 请求/响应模型更加高效。

  • 低延迟:由于不需要为每个请求建立新的连接,WebSocket 可以显著减少延迟。

  • 节省带宽:在 WebSocket 中,只有数据被发送而不需要携带大量的头部信息,这减少了带宽的消耗。

2 实现步骤

实施前提:默认在springBoot环境下实施

2.1 导入依赖

<!--WebSocket依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version> 3.3.4</version>
</dependency>

2.2 编写代码

WebSocketConfig:主要实现websocket的一些配置
package com.hyh.admin.config.websocket;import org.springframework.boot.web.servlet.ServletContextInitializer;
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;import javax.servlet.ServletContext;
import javax.servlet.ServletException;/*** WebSocket配置* @author hyh*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements ServletContextInitializer {/**  ServerEndpointExporter 作用*  这个Bean会自动注册使用@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}/** 解除websocket对数据大小的限制* @param servletContext Servlet上下文**/@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {// 解除websocket对数据大小的限制servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","10240000");servletContext.setInitParameter("org.apache.tomcat.websocket.binaryBufferSize","10240000");}
}
WebSocketSingleServe:具体的实现聊天的实时代码需求
package com.hyh.admin.config.websocket;import com.hyh.ad.common.core.domain.model.SysUser;
import com.hyh.admin.config.websocket.context.SpringBeanContext;
import com.hyh.admin.domain.Messages;
import com.hyh.admin.service.MessageService;
import com.hyh.admin.sys.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** WebSocket 单聊服务端*/
@ServerEndpoint("/singleChat/{username}")
@Component
public class WebSocketSingleServe implements InitializingBean {private static final Logger log = LoggerFactory.getLogger(WebSocketSingleServe.class);// 记录当前在线的连接public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(@PathParam("username") String username, Session session) {// 将用户的session放入map中session.getUserProperties().put("username", username);sessionMap.put(username, session);log.info("用户:{}",session.getUserProperties().get("username"));log.info("用户:{} 连接成功,session:{},总数:{}", username, session.getId(), sessionMap.size());}/*** 连接关闭调用的方法*/@OnClosepublic void onClose(Session session) {try {sessionMap.values().remove(session);log.info("连接关闭,session:{},总数:{}", session.getId(), sessionMap.size());} catch (Exception e) {log.error("连接关闭异常:{}", e.getMessage());}}/*** 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session fromSession) {// 假设消息格式为 "username:file:data"String[] parts = message.split(":", 3);if (parts.length == 3) {String targetUsername = parts[0].trim(); // 目标用户String type = parts[1].trim(); // 消息类型(text/file)String content = parts[2].trim(); // 消息内容log.info("收到消息:{},类型:{},内容:{}", targetUsername, type, content);// 根据类型处理消息if ("text".equals(type)) {// 发送文本消息sendMessageToUser(targetUsername, content, type);} else if ("image".equals(type)) {// 发送文件消息sendFileToUser(targetUsername, content, type);}else if ("file".equals(type)) {// 发送文件消息sendFileToUser(targetUsername, content, "file");}// 消息持久化String username = (String) fromSession.getUserProperties().get("username");saveMessage(username, targetUsername, content, type);}}/** 消息持久化*/private void saveMessage(String sendUsername, String targetUsername, String msg, String type) {// 保存消息try {MessageService messageService = SpringBeanContext.getContext().getBean(MessageService.class);ISysUserService sysUserService = SpringBeanContext.getContext().getBean(ISysUserService.class);SysUser targetUser = sysUserService.selectUserByUserName(targetUsername);Long targetUserId = targetUser.getId();SysUser sendUser = sysUserService.selectUserByUserName(sendUsername);Long userId = sendUser.getId();Messages messages = new Messages();messages.setSenderId(userId);messages.setReceiverId(targetUserId);messages.setContent(msg);messages.setMessageType(type); // 保存消息类型messageService.addMessage(messages);log.info("消息持久化成功");} catch (Exception e) {log.error("消息持久化失败:{}", e.getMessage());}}/**  发送文件给用户*/private void sendFileToUser(String targetUsername, String fileContent, String type) {Session targetSession = sessionMap.get(targetUsername);if (targetSession != null) {try {targetSession.getBasicRemote().sendText(type + "|" + fileContent); // 文件发送格式log.info("发送文件给用户:{},发送成功", targetUsername);} catch (IOException e) {log.error("发送文件失败:{}", e.getMessage());}}}/*** 发生错误时调用*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发生错误,session:{} ,错误信息:{}", session.getId(), error);}/*** 服务端发送消息给指定用户* @param username 目标用户* @param message 消息内容*/public void sendMessageToUser(String username, String message, String type) {Session session = sessionMap.get(username);if (session != null && session.isOpen()) {try {session.getBasicRemote().sendText(type + "|" + message);log.info("发送给用户:{},内容:{}", username, message);} catch (IOException e) {log.error("发送消息失败:{}", e.getMessage());}} else {log.warn("用户:{} 不在线,无法发送消息", username);}}@Overridepublic void afterPropertiesSet() throws Exception {log.info("WebSocket服务端启动");}
}

  onopen方法主要用于连接的的方法,所有和websocket发起连接的客户端都会经过这个方法。

  onmessage方法主要用于发送消息的方法,其中定义了发送消息的格式,可以自行定义。

   前端代码:

 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>聊天界面</title><style>body { font-family: Arial, sans-serif; }#messages { border: 1px solid #ccc; height: 300px; overflow-y: scroll; margin-bottom: 10px; }input, button { margin: 5px; }</style>
</head>
<body>
<h2>聊天界面</h2>
<input type="text" id="targetUser" placeholder="输入目标用户名...">
<input type="text" id="message" placeholder="输入消息...">
<button id="sendBtn">发送</button>
<div id="messages"></div>
<img src="https://c-ssl.duitang.com/uploads/item/202003/27/20200327141738_ulbvu.jpg" alt="">
<script>const username = prompt("请输入您的用户名:"); // 获取当前用户的用户名const socket = new WebSocket(`ws://127.0.0.1:8088/singleChat/${username}`);socket.onopen = function() {console.log(`${username} 已连接`);};socket.onmessage = function(event) {const messagesDiv = document.getElementById("messages");messagesDiv.innerHTML += `<p>${event.data}</p>`;messagesDiv.scrollTop = messagesDiv.scrollHeight; // 滚动到底部};document.getElementById("sendBtn").onclick = function() {const targetUser = document.getElementById("targetUser").value;const messageInput = document.getElementById("message").value;const message = `${targetUser}:text:${messageInput}`; // 格式化消息socket.send(message);// 显示自己发送的消息const messagesDiv = document.getElementById("messages");messagesDiv.innerHTML += `<p>我: ${messageInput}</p>`;messagesDiv.scrollTop = messagesDiv.scrollHeight; // 滚动到底部document.getElementById("message").value = "";  // 清空输入框};
</script>
</body>
</html>

  

vue的部分代码和项目完整的截图为:

 this.socket = new WebSocket(`ws://127.0.0.1:8088/singleChat/${localStorage.getItem("username")}`);this.socket.onopen = () => {console.log(localStorage.getItem("username") + " 连接成功");};// 只设置一次 onmessage 处理逻辑this.socket.onmessage = (event) => {const message = event.data; // 假设格式为 "type:content"const parts = message.split("|"); // 按冒号分割if (parts.length === 2) {const type = parts[0].trim(); // 消息类型const content = parts[1].trim(); // 消息内容this.contactRecord.push({id: Date.now(), // 使用时间戳作为消息 IDsenderId: this.user.id, // 或者其他用户的 IDcontent: content,messageType: type, // 添加类型});// 进度条滚动到底部this.scrollToBottom();}};},

 

需要源码的请私信我:

谢谢各位的支持!!! 

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

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

相关文章

软件设计师-上午题-15 计算机网络(5分)

计算机网络题号一般为66-70题&#xff0c;分值一般为5分。 目录 1 网络设备 1.1 真题 2 协议簇 2.1 真题 3 TCP和UDP 3.1 真题 4 SMTP和POP3 4.1 真题 5 ARP 5.1 真题 6 DHCP 6.1 真题 7 URL 7.1 真题 8 浏览器 8.1 真题 9 IP地址和子网掩码 9.1 真题 10 I…

C++:map 和 set 的使用

前言 平衡二叉搜索树 ( AVL树 ) 由于二叉搜索树在特殊情况下&#xff0c;其增删查的效率会降低到 O ( N )&#xff0c;因此对二叉搜索树进行改良&#xff0c;通过旋转等方式将其转换为一个左右均衡的二叉树&#xff0c;这样的树就称为平衡二叉搜索树&#xff0c;又称 AVL树。…

Vue 自定义icon组件封装SVG图标

通过自定义子组件CustomIcon.vue使用SVG图标&#xff0c;相比iconfont下载文件、重新替换更节省时间。 子组件包括&#xff1a; 1. Icons.vue 存放所有SVG图标的path 2. CustomIcon.vue 通过icon的id索引对应的图标 使用的时候需要将 <Icons></Icons> 引到使用的…

面相小白的php反序列化漏洞原理剖析

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理反序列化漏洞的一些成因原理 建议学习反序列化之前 先对php基础语法与面向对象有个大体的了解 (我觉得我整理的比较细致&#xff0c;了解这俩是个啥就行) 漏洞实战情况 这个漏洞黑盒几乎不会被发现&am…

ReactPress:深入解析技术方案设计与源码

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎提出宝贵的建议&#xff0c;欢迎一起共建&#xff0c;感谢Star。 ReactPress是一个基于React框架开发的开源发布平台&#xff0c;它不仅仅是一个简单的博客系统&#xff0c;更是一个功能全…

canal1.1.7使用canal-adapter进行mysql同步数据

重要的事情说前面&#xff0c;canal1.1.8需要jdk11以上&#xff0c;大家自行选择&#xff0c;我这由于项目原因只能使用1.1.7兼容版的 文章参考地址&#xff1a; canal 使用详解_canal使用-CSDN博客 使用canal.deployer-1.1.7和canal.adapter-1.1.7实现mysql数据同步_mysql更…

SpringBoot之定时任务

1. 前言 本篇博客是个人的经验之谈&#xff0c;不是普适的解决方案。阅读本篇博客的朋友&#xff0c;可以参考这里的写法&#xff0c;如有不同的见解和想法&#xff0c;欢迎评论区交流。如果此篇博客对你有帮助&#xff0c;感谢点个赞~ 2. 场景 我们讨论在单体项目&#xff0c…

绿色能源发展关键:优化风电运维体系

根据QYResearch调研团队最新发布的《全球风电运维市场报告2023-2029》显示&#xff0c;预计到2029年&#xff0c;全球风电运维市场的规模将攀升至307.8亿美元&#xff0c;并且在接下来的几年里&#xff0c;其年复合增长率&#xff08;CAGR&#xff09;将达到12.5%。 上述图表及…

前端 Canvas 绘画 总结

目录 一、使用案例 1、基础使用案例 2、基本案例改为直接JS实现 二、相关资料 1、API教程文档 2、炫酷案例 一、使用案例 1、基础使用案例 使用Canvas的基本步骤&#xff1a; 1、需要一个canvas标签 2、需要获取 画笔 对象 3、使用canvas提供的api进行绘图 <!--…

力扣排序455题(分发饼干)

假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。 但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i],这是能 让孩子们满足胃口的饼干的最小尺寸;并且每块饼 干j&#xff0c;都有一个尺寸 s[j]。如果 s[j]> g[i]&…

C语言 | Leetcode C语言题解之第537题复数乘法

题目&#xff1a; 题解&#xff1a; bool parseComplexNumber(const char * num, int * real, int * image) {char *token strtok(num, "");*real atoi(token);token strtok(NULL, "i");*image atoi(token);return true; };char * complexNumberMulti…

Android使用scheme方式唤醒处于后台时的App场景

场景&#xff1a;甲App唤醒处于后台时的乙App的目标界面Activity&#xff0c;且乙App的目标界面Activity处于最上层&#xff0c;即已经打开状态&#xff0c;要求甲App使用scheme唤醒乙App时&#xff0c;达到跟从桌面icon拉起App效果一致&#xff0c;不能出现只拉起了乙App的目标…

如何对接低价折扣相对稳定电影票渠道?

对接低价折扣电影票渠道需要经过一系列步骤&#xff0c;以确保能够为用户提供优惠且可靠的购票体验。以下是一个基本的对接流程&#xff1a; 1.市场调研&#xff1a; 调研市场上的电影票销售渠道&#xff0c;了解主要的电影票批发商和分销商。分析竞争对手的折扣电影票服务&a…

【上云拼团Go】如何在腾讯云双十一活动中省钱

1. 前言 双十一已经成为了全球最大的购物狂欢节&#xff0c;除了电商平台的优惠&#xff0c;云计算服务商也纷纷在这个期间推出了诱人的促销活动。腾讯云作为中国云计算的领军企业之一&#xff0c;每年双十一的活动都吸引了大量开发者、企业和个人用户参与。那么&#xff0c;在…

新能源企业在精益变革过程中可能会遇到哪些困难?

在绿色转型的浪潮中&#xff0c;新能源企业作为推动社会可持续发展的先锋力量&#xff0c;正加速迈向精益化管理的新阶段。然而&#xff0c;这条变革之路并非坦途&#xff0c;而是布满了未知与挑战。本文&#xff0c;天行健王春城老师将深入探讨新能源企业在精益变革过程中可能…

Maven的安装配置

文章目录 一、MVN 的下载二、配置maven2.1、更改maven/conf/settings.xml配置2.2、配置环境变量一、MVN 的下载 还是那句话,要去就去官网或者github,别的地方不要去下载。我们下载binaries/ 目录下的 cd /opt/server wget https://downloads.apache.org/maven/maven-3/3.9.6/…

OpenCV视觉分析之目标跟踪(10)估计两个点集之间的刚性变换函数estimateRigidTransform的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算两个2D点集之间的最优仿射变换 estimateRigidTransform 是 OpenCV 中的一个函数&#xff0c;用于估计两个点集之间的刚性变换&#xff08;即…

块存储、文件存储和对象存储详细介绍

块存储、文件存储和对象存储介绍 块存储&#xff1a;像跑车&#xff0c;因为它们都能提供快速的响应和高性能&#xff0c;适合需要即时数据访问的场景&#xff0c;比如数据库和虚拟化技术。 文件存储&#xff1a;像货车&#xff0c;因为它们都能承载大量货物&#xff08;文件&…

A019基于SpringBoot的校园闲置物品交易系统

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…

基于YOLO11/v10/v8/v5深度学习的煤矿传送带异物检测系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…