Spring Boot + WebSocket实现网页在线实时聊天

部分代码

首先创建springboot项目并引入依赖:

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

服务端核心代码

@Component
@ServerEndpoint("/chat/lobby")
public class LobbyChat {@OnOpenpublic void onOpen(Session session) throws IOException {/** @description: TODO 链接建立时调用该方法* @params: [session]   //连接发起者的会话对象* @return: void* @author: QGQ* @dateTime: 2022/3/1 18:59*/
//        Info.increaseOnlineCount();//从querystring中取出用户输入的用户名并解码然后和session对象一起保存到user对象中User user = new User(URLDecoder.decode(session.getQueryString().split("=")[1],"UTF-8"),session);Info.addUser(user);//向所有用户推送最新的在线者信息for (User u: Info.getUserList()) {send(u.getSession(),MsgHelper.generateUserInfo(Info.getUserList()));}System.out.println("一名用户上线,"+user.toString()+"当前在线人数为:"+ Info.getOnlineCount());}@OnClosepublic void onClose(Session session) throws IOException {/** @description: TODO 某用户下线,更新在线人数和在线者列表* @params: [session]* @return: void* @author: QGQ* @dateTime: 2022/3/1 19:01*/System.out.println("用户"+Info.getUser(session)+"已下线,当前在线人数:"+(Info.getOnlineCount()-1));Info.removeUser(session);//向所有用户推送最新的在线者信息for (User u: Info.getUserList()) {send(u.getSession(),MsgHelper.generateUserInfo(Info.getUserList()));}}@OnErrorpublic void onError(Session session, Throwable error){System.out.println("发生错误!");error.printStackTrace();}@OnMessagepublic void onMessage(String msg,Session session) throws IOException {/** @description: TODO 根据收到消息的类型将收到的消息发给所有在线者或个人* @params: [session]* @return: void* @author: QGQ* @dateTime: 2022/3/1 19:51*///使用jackson的API将前端发来的封装好的消息对象转成mapObjectMapper objectMapper = new ObjectMapper();Map<String,String> received = objectMapper.readValue(msg, new TypeReference<Map<String,String>>(){});
//        System.out.println(received);String msgObj = null;   //用于封装规定格式的消息对象User sender = Info.getUser(session);    //获取发送者对象if (received.get("type").equals("lobby")){//该type值表示这是发往大厅的消息System.out.println("用户"+Info.getUser(session)+"发出的消息:"+received.get("content"));msgObj = MsgHelper.generateUserMsg(sender.getUsername(),sender.getSession().getId(),"lobby",received.get("content"));for (User u: Info.getUserList()) {send(u.getSession(),msgObj);}}if (received.get("type").equals("friend")){//该type值表示这条消息是发给某人的System.out.println(received);msgObj = MsgHelper.generateUserMsg(sender.getUsername(),sender.getSession().getId(),"friend",received.get("content"));
//            send(Info.getUser(session).getSession(),msgObj);send(Info.getUser(received.get("sessionID")).getSession(),msgObj);}}public static void send(Session receiver,String msg) throws IOException {/** @description: TODO 向用户发送消息* @params: [receiver, msg] //前者为接受者,后者为发送的内容* @return: void* @author: QGQ* @dateTime: 2022/3/3 20:20*/receiver.getBasicRemote().sendText(msg);}}

前端核心代码:

let app = Vue.createApp({data(){return {username:"",    //当前用户的昵称lobby_input:"hello", //大厅输入框的内容friend_input:"",   //私聊输入框的内容msg_records_f: [],    //私聊框消息记录,格式为{type:"message",sender:xxx,senderID:xxx,to:xxx,time:xxx,content:xxx}msg_records_l:[],   //大厅消息记录,格式同上received_msg_f: "", //私聊框收到的最新消息online_count: 0,    //在线人数onlineUsers:null,   //在线者列表pri_chat_obj: {username:"未开始私聊",sessionId:-1}, //当前私聊对象,格式为{username:xxx,sessionID:xxx}socket: null,   //websocket对象btnChatMovedActiveIndex: -1,   //决定CSS类.btn-chat-moved是否生效}},methods:{sendMsgToF(){// 向私聊对象发送消息if(this.pri_chat_obj.sessionId != -1){if(this.friend_input!=""){console.log(this.msgObjF);this.socket?.send(this.msgObjF);let d= new Date();let timeStr = d.getHours() + "时" + d.getMinutes() +"分" + d.getSeconds() + "秒";this.msg_records_f.push({sender:this.username,time:timeStr,content:this.friend_input});this.friend_input = "";}}else {alert("请先选择私聊对象");}},sendMsgToL(){//发送消息到大厅,没输入任何文字时不发送if (this.lobby_input !== ""){this.socket?.send(this.msgObjL);this.lobby_input = "";}},chatWith(user){//切换私聊对象为userif(user!==this.pri_chat_obj){this.pri_chat_obj = user;this.msg_records_f = [];}},getUserBySessionID(id){//通过sessionID获取发送者对象for (let i = 0; i < this.onlineUsers.length; i++) {if (this.onlineUsers[i].sessionId === id){return this.onlineUsers[i];}}}},computed:{msgObjL(){//要发送给后端的大厅消息对象,格式为{type:lobby,content:xxx}return  JSON.stringify({type:"lobby",content:this.lobby_input});},msgObjF(){//要发送给后端的私聊消息对象,格式为:{type:friend,sessionID:xxx,content:xxx}return  JSON.stringify({type:"friend",sessionID:this.pri_chat_obj.sessionId,content:this.friend_input});}},watch:{received_msg_f(val){console.log(val)}},mounted(){let name = window.prompt("请输入你在本次聊天中要使用的昵称");while (name === ""||name == null){name = window.prompt("请输入一个昵称!");}this.username = name;let webSocket = new WebSocket("ws://127.0.0.1:8080/chat/lobby?username="+this.username);webSocket.onopen = function (){console.log("链接建立成功");app.$data.socket = webSocket;// app.$data.online_count++;}webSocket.onclose = function (){console.log("连接已关闭");}webSocket.onerror = function (err){alert("连接服务器失败!");console.log(err);}//收到消息时调用webSocket.onmessage = function (event){console.log(event.data)let msgObj = JSON.parse(event.data);    //获取后端封装的消息对象// app.$data.received_msg_f = msgObj.content;  //修改最新收到的消息console.log(msgObj)if(msgObj.type==="message"){//该type值表示这是某个用户发送的消息if(msgObj.to==="lobby"){app.$data.msg_records_l.push(msgObj);   //将收到的消息加入消息记录}if (msgObj.to==="friend"){app.$data.msg_records_f.push(msgObj);app.$data.pri_chat_obj = app.getUserBySessionID(msgObj.senderID);}}if (msgObj.type=="info"){//该type值表示这是服务器推送的在线用户信息// console.log(msgObj);app.$data.online_count = msgObj.onlineCount;app.$data.onlineUsers = msgObj.userList;}}//当窗口被关闭时,先关闭ws连接window.onbeforeunload = function (){webSocket.close();app.$data.socket = null;app.$data.online_count--;}}
}).mount("#app");

完整代码可在Gitee查看.

演示

先输入要使用的昵称
在这里插入图片描述
同样方法打开三个标签页
在这里插入图片描述
在大厅大消息所有人都会收到
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
鼠标在在线者列表上悬浮会出现chat按钮,点击可开始私聊
在这里插入图片描述
向私聊对象发送消息,只有他一个人会收到,Tony收到消息
在这里插入图片描述
Thor没有收到在这里插入图片描述
Peter收到Tony的回复
在这里插入图片描述

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

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

相关文章

chatgpt赋能python:Python跳过SSL验证:安全风险与解决方案

Python跳过SSL验证&#xff1a;安全风险与解决方案 随着互联网的快速发展&#xff0c;网络安全问题越来越受到关注。在这个过程中&#xff0c;SSL&#xff08;Secure Sockets Layer&#xff09;的作用至关重要。SSL 是一种加密协议&#xff0c;用于保护网络通信中的敏感信息。…

详解阿里巴巴1688日常业务中的榜单算法

导读&#xff1a;本文详解阿里巴巴1688日常业务中的榜单算法。 作者&#xff1a;阿里集团 新零售技术事业群 CBU技术部 来源&#xff1a;大数据DT&#xff08;ID&#xff1a;hzdashuju&#xff09; 在1688日常的业务场景中&#xff0c;榜单&#xff08;如图6-14所示&#xff09…

马云发内部信: 2014阿里巴巴ALL IN移动电商

这是马云的一封和员工沟通的内部信&#xff0c;在内部信中马云阐述了其对未来的战略&#xff0c;马云认为无线互联网时代移动电商将必定是移动互联网时代最重要的领域。以下为信件全文。 各位阿里人: 春节过去了。这个春节我和大家一样&#xff0c;密切关注着移动互联网带来的…

阿里主动改革,再次引领国内公司治理新浪潮

北京时间2023年5月18日美股盘前&#xff0c;阿里公布2023财年Q4及全年财报&#xff0c;整体财务状况符合市场预期&#xff0c;但推动组织变革的进度&#xff0c;却给了市场一个“惊喜”。 财报中&#xff0c;阿里宣布了整体组织变革背景下&#xff0c;旗下数个业务的未来方向&…

【大数据AI人工智能】每个现代数据科学家都必须阅读的 6 篇论文| 6 Papers Every Modern Data Scientist Must Read

6 Papers Every Modern Data Scientist Must Read 每个现代数据科学家都必须阅读的 6 篇论文 A list of some of the most important modern fundamentals of Deep Learning everyone in the field show be familiar with 该领域的每个人都熟悉深度学习的一些最重要的现代基础知…

如何查询某只股票的历史股价?

一个可以在线查询股票历史股价的小工具&#xff0c;目前可以查询A股、港股、美股所有个股的历史股价&#xff0c;另外还可以下载个股的历史股价Excel&#xff0c;做分析、研究挺有用的 只要两步就能下载&#xff1a; 填股票代码、邮箱5分钟后收到股票历史数据Excel **【手机…

全年股价暴涨超110% TTD能否杀出巨头们的围墙花园?

有时&#xff0c;知名度较低的股票也可以成为市场赢家。在过去的一年里&#xff0c;The Trade Desk这样一家知名度并不是很高的股票&#xff0c;累计涨幅却高达117.75%&#xff0c;这样的表现不得不让人将目光聚焦于此。 作为一家美国DSP领域的"独角兽"&#xff0c;…

Meta股价暴跌,市值蒸发2000亿,元宇宙受挫?

在这个过山车般的财报季&#xff0c;科技巨头们一公布季报&#xff0c;就有好多人要吃救心丸。 Facebook母公司Meta&#xff0c;美国当地时间周三发布的季报揭示了一个惊人的统计数据&#xff1a;该公司的增长有史以来第一次在全球范围内停滞不前。 截至当地时间周四下午&…

第一个维基站点问世 | 历史上的今天

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 3 月 25 日&#xff0c;在 1998 年的今天&#xff0c;为迎接 2000 年这一世界性节日的到来&#xff0c;人民日报发起&#xff0c;人民日报国际部、八达岭长城特…

2023年6月编程语言排行

2023年6月 TIOBE指数 June Headline: Will Python remain number 1? Python has been the TIOBE index annual award winner for 3 times in the last 5 years. It has grown in popularity like crazy, due to boosts in the fields of data sciences and artificial intell…

价格最高降75%、API函数调用上线、上下文长度提高4倍,OpenAI凌晨再给ChatGPT、GPT-4加码!...

整理 | 屠敏 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 就在今天凌晨&#xff0c;OpenAI 马不停蹄地又双叒叕更新啦&#xff01; 这一次&#xff0c;不仅重磅升级了 ChatGPT 背后的 GPT-3.5-turbo 模型、以及最先进的 GPT-4 文本生成模型&#xff0c;而且大幅…

《花雕学AI》30:ChatGPT的资料来源比例排名前20名是什么?

引言&#xff1a;ChatGPT是一款由OpenAI开发的人工智能聊天机器人&#xff0c;它可以回答各种问题&#xff0c;并生成创意内容&#xff0c;如诗歌、故事、代码等。 ChatGPT的核心技术是基于GPT-3.5和GPT-4的大型语言模型&#xff0c;它可以利用从网路上收集的大量文本资料来进行…

【英语】大学英语CET考试,写作部分(论述文+应用文,6篇范文)

文章目录 3项评分标准&#xff08;内容&结构&#xff0c;语言&#xff09;0.1 论述文个人小结 1、论述文&#xff1a;审题与功能句2、论述文&#xff1a;修饰内容和名言模板3、论述文&#xff1a;现象作文&利弊分析4、论述文&#xff1a;给出权威论据和有侧重的现象5、…

清华发布 KoLA 评测集,分4个认知层级评测LLM,GPT-4竟不是第一?

作者 | Python 预训练语言模型&#xff08;PLM&#xff09;刷GLUE&#xff0c;SuperGLUE&#xff0c;甚是常见&#xff1b;那ChatGPT等大语言模型&#xff08;LLM&#xff09;刷什么榜呢&#xff1f;现在常用的榜单&#xff0c;例如MMLU评测了57个学科知识&#xff0c;Big-Benc…

屏幕挂灯是不是智商税?明基ScreenBar Halo屏幕挂灯初体验

目录 一、屏幕挂灯是不是智商税&#xff1f;二、文心一言眼里的屏幕挂灯1、明基ScreenBar Halo屏幕挂灯2、屏幕挂灯和普通台灯哪个好&#xff1f; 三、屏幕挂灯初体验四、使用体验五、无线控制器六、专业角度分析1、屏幕工作照明&#xff0c;不是随便一盏灯就可以2、引导光线照…

微软小冰发布社交APP“小冰岛”:不是元宇宙,是虚拟版微信

元宇宙是一个空间的概念&#xff0c;小冰岛更像是“灵魂”&#xff0c;是一场人类和AI融合的探索。 从微软拆分的一年后&#xff0c;9月22日&#xff0c;在小冰第九代发布会上&#xff0c;小冰公司发布了首个社交平台APP“小冰岛”。 和传统的社交平台不太相同的是&#xff0c…

刷题算法总结

一、数据结构的存储方式 数据结构的存储方式只有两种&#xff1a;数组&#xff08;顺序存储&#xff09;和链表&#xff08;链式存储&#xff09;。 二、数据结构的基本操作 对于任何数据结构&#xff0c;其基本操作&#xff1a;增删查改。 各种数据结构的遍历 访问无非两种…

【回答问题】ChatGPT上线了!推荐40个以上比较好的目标检测模型

推荐40个以上比较好的目标检测模型? 目标检测是指在图像中找到并标识出特定目标的计算机视觉任务。近年来,机器学习技术的发展使得目标检测取得了长足进步。目前有许多优秀的目标检测模型,下面是推荐的40个以上的比较好的目标检测模型: R-CNN (Regions with CNN features…

足球推荐预测

彼得堡联 - 雷丁 我看好让负&#xff0c;看好大家私&#xff0c;两队在前段时间都是很少有胜绩&#xff0c;竞技状态都比较低迷&#xff0c;而且前不久遇到了同一支球队考文垂&#xff0c;战绩都不漂亮&#xff0c;两队实力相差程度不大&#xff0c;所以让负几率大一些

世预赛乌拉圭VS哥伦比亚最新赛事解析:客场保平属性强怎么下单

乌拉圭VS哥伦比亚南美预选赛临场交流:苏亚雷斯或可出场瓦尔韦德身陷囹吾&#xff0c;萨帕塔来袭乌拉圭能否首回合取胜&#xff01;10月开门红&#xff0c;英锦赛吉灵汉姆负加米尔顿让平和林肯城负全部拿捏&#xff0c;希望跟上的朋友能够点个赞支持一下&#xff0c;同时相信失利…