聊天广场(Vue+WebSocket+SpringBoot)

由于心血来潮想要做个聊天室项目 ,但是仔细找了一下相关教程,却发现这么多的WebSocket教程里面,很多都没有介绍详细,代码都有所残缺,所以这次带来一个比较完整得使用WebSocket的项目。

目录

一、效果展示

二、准备工作

一、前端框架,Vue + elementUI组件 +JsCookie

二、后端 SpringBoot + websocket包

三、前端代码

四、后端代码


一、效果展示

1.用户交流


二、准备工作

一、前端框架,Vue + elementUI组件 +JsCookie

新建一个vue项目

引入以下组件与依赖

npm i element-ui -S
npm install js-cookie

二、后端 SpringBoot + websocket包

创建SpringBoot项目后

在pom.xml文件中引入以下依赖:

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

注意项目前端为8081端口,后端为8080端口,所以先运行后端再运行前端


三、前端代码

在App.vue中即可引入以下代码:

html:

<template><div id="Layout"><el-container><el-aside width="200px">Aside</el-aside><el-container><el-header style="background-color: rgb(245, 245, 245); border-bottom: 1px solid grey;"><h3>聊天广场</h3></el-header><el-main style="background-color: rgb(244, 245, 247);min-height: 700px; max-height: 700px; "><div id="chatContent" style="padding-left: 10px; line-height: normal; "><!-- 循环输出对话内容 --><el-scrollbar v-for="(message, index) in messages" :key="index"><div ref="scrollbar" v-if="message.sender !== senderName" class="chat-message" id="ChatContentCard" style=" background-color: white;margin-top: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)  "><el-avatar :size="40"src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar><div class="message-content" style="width: 100%;"><div style="text-align: left; text-indent: 1em;"> {{ message.sender }}</div><div id="chatContentText">{{ message.text }}</div></div></div><div ref="scrollbar" v-if="message.sender === senderName" id="myChatContentCard"><el-avatar :size="40"src="https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"></el-avatar><div class="message-content" style="width: 100%;"><div style="text-align: left; text-indent: 1em;"> {{ message.sender }}</div><div id="chatContentText">{{ message.text }}</div></div></div></el-scrollbar></div></el-main><!-- 底层交互框 --><el-footer style="height: 190px; background-color: rgb(244, 245, 247); "><div id="Gadget" style="background-color: rgb(244, 245, 247); height: 35px; margin-bottom: 10px;"><el-upload class="upload-demo" ref="upload" action="https://jsonplaceholder.typicode.com/posts/":on-preview="handlePreview" :on-remove="handleRemove" :file-list="fileList" :auto-upload="false" style="float: left;"><el-button slot="trigger" size="small" type="primary"><i class="el-icon-picture-outline-round"></i></el-button><el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button></el-upload></div><el-form @submit.native.prevent="sendMessage"style="background-color: rgb(244, 245, 247); height: 80%; width: 100%; position: relative;"><el-input v-model="messageInput" rows="4" resize="none" type="textarea" placeholder="请输入内容......."@keyup.enter="sendMessage" style="height: 100%; max-height: 60px; "></el-input><div style="text-align: right; background-color: rgb(244, 245, 247); margin-top: 34px;"><el-button type="primary" @click="sendMessage">发送</el-button></div></el-form></el-footer></el-container></el-container></div>
</template>

script:

<script>
import Cookies from 'js-cookie';export default {computed: {senderName() {return Cookies.get('account') || '游客';}},name: 'App',data() {return {messages: [],messageInput: '',ws: null,fileList: []};},mounted() {this.initWebSocket();},beforeDestroy() {this.closeWebSocket();},methods: {initWebSocket() {this.ws = new WebSocket('ws://localhost:8080/chat');this.ws.onopen = () => {console.log('Connected to server.');};this.ws.onmessage = (event) => {try {let messageData;if (isJson(event.data)) {messageData = JSON.parse(event.data);} else {messageData = { text: event.data };}this.messages.push({sender: messageData.sender || 'Anonymous',text: messageData.text,});// 使用Vue.nextTick确保DOM更新后再执行滚动操作this.$nextTick(() => {// 确保scrollbar存在且已渲染if (this.$refs.scrollbar) {// 直接滚动到底部,不需要使用contentSize// this.$refs.scrollbar.$el.scrollTop = this.$refs.scrollbar.$el.scrollHeight;}});} catch (error) {console.error('Error parsing message:', error);}};// 辅助函数,检查字符串是否可能是JSON格式function isJson(str) {try {JSON.parse(str);} catch (e) {return false;}return true;}this.ws.onerror = (error) => {console.error('WebSocket error:', error);};this.ws.onclose = () => {console.log('Disconnected from server.');};},sendMessage() {console.log('调用sendMessage');const senderName = Cookies.get('account');if (senderName === null) {this.senderName = "游客";}if (this.messageInput.trim() !== '') {this.ws.send(JSON.stringify({ sender: senderName, text: this.messageInput }));this.messageInput = ''; // 清空输入框}},closeWebSocket() {if (this.ws && this.ws.readyState === WebSocket.OPEN) {this.ws.close();}},// 文件上传函数
submitUpload() {this.$refs.upload.submit();},handleRemove(file, fileList) {console.log(file, fileList);},handlePreview(file) {console.log(file);}},
};
</script>

css:

<style scoped>
.chat-message {display: flex;align-items: center;margin-bottom: 10px;
}.message-content {margin-left: 10px;
}#Layout {line-height: normal;
}/* 添加动画关键帧 */
@keyframes slideInFromLeft {0% {transform: translateX(-100%);opacity: 0;}100% {transform: translateX(0);opacity: 1;}
}#ChatContentCard {min-height: 80px;width: 50%;/* 应用动画 */animation: slideInFromLeft 0.3s ease-in-out forwards;border-radius: 30px
}#chatContentText {width: 99%;overflow-wrap: break-word;}.el-header,
.el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;
}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;
}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;
}body>.el-container {margin-bottom: 40px;
}.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {line-height: 260px;
}.el-container:nth-child(7) .el-aside {line-height: 320px;
}#myChatContentCard{display: flex;align-items: center;margin-bottom: 10px;margin-left: 50%;min-height: 80px;width: 50%;/* 应用动画 */animation: slideInFromRight 0.3s ease-in-out forwards;border-radius: 30px;background-color: rgb(149, 236, 105);margin-top: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) }@keyframes slideInFromRight {0% {transform: translateX(100%);opacity: 0;}100% {transform: translateX(0);opacity: 1;}
}</style>

注意: 这个项目中如果script需要进行修改,由于我这里完成了一个登陆系统,所以采用了对Cookie的使用,而如果只是体验的话,只需要把Cookie去掉将其改为游客+随机字符串去替代即可。

前端启动

npm run serve


四、后端代码

WebSocket配置:

1.WebSocketConfig.java

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new ChatWebSocketHandler(), "/chat").setAllowedOrigins("*");}
}

 2.ChatWebSocketHandler.java

@Slf4j
public class ChatWebSocketHandler extends TextWebSocketHandler {private static final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.add(session);broadcast("欢迎新的小伙伴加入");}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {broadcast(message.getPayload());}private void broadcast(String message) {log.info("服务器广播数据:"+message);sessions.forEach(session -> {try {session.sendMessage(new TextMessage(message));} catch (Exception e) {e.printStackTrace();}});}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {sessions.remove(session);}
}

 后端启动:

 


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

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

相关文章

html+css+js图片手动轮播

源代码在界面图片后面 轮播演示用的几张图片是Bing上的&#xff0c;直接用的几张图片的URL&#xff0c;谁加载可能需要等一下&#xff0c;现实中替换成自己的图片即可 关注一下点个赞吧&#x1f604; 谢谢大佬 界面图片 源代码 <!DOCTYPE html> <html lang&quo…

安全测试之使用Docker搭建SQL注入安全测试平台sqli-labs

1 搜索镜像 docker search sqli-labs 2 拉取镜像 docker pull acgpiano/sqli-labs 3 创建docker容器 docker run -d --name sqli-labs -p 10012:80 acgpiano/sqli-labs 4 访问测试平台网站 若直接使用虚拟机&#xff0c;则直接通过ip端口号访问若通过配置域名&#xff0…

第十五章 Nest Pipe(内置及自定义)

NestJS的Pipe是一个用于数据转换和验证的特殊装饰器。Pipe可以应用于控制器&#xff08;Controller&#xff09;的处理方法&#xff08;Handler&#xff09;和中间件&#xff08;Middleware&#xff09;&#xff0c;用于处理传入的数据。它可以用来转换和验证数据&#xff0c;确…

【Linux进阶】文件系统5——ext2文件系统(inode)

1.再谈inode (1) 理解inode&#xff0c;要从文件储存说起。 文件储存在硬盘上&#xff0c;硬盘的最小存储单位叫做"扇区"&#xff08;Sector&#xff09;。每个扇区储存512字节&#xff08;相当于0.5KB&#xff09;。操作系统读取硬盘的时候&#xff0c;不会一个个…

记录excel表生成一列按七天一个周期的方法

使用excel生成每七天一个周期的列。如下图所示&#xff1a; 针对第一列的生成办法&#xff0c;使用如下函数&#xff1a; TEXT(DATE(2024,1,1)(ROW()-2)*7,"yyyy/m/d")&" - "&TEXT(DATE(2024,1,1)(ROW()-1)*7-1,"yyyy/m/d") 特此记录。…

charles使用教程

安装与配置 下载链接&#xff1a;https://www.charlesproxy.com/download/ 进行移动端抓包&#xff1a; 电脑端配置&#xff1a; 关闭防火墙 Proxy–>勾选 macOS Proxy Proxy–>Proxy Setting–>填入代理端口8888–>勾选Enable transparent http proxying 安装c…

昇思25天学习打卡营第1天|初识MindSpore

# 打卡 day1 目录 # 打卡 day1 初识MindSpore 昇思 MindSpore 是什么&#xff1f; 昇思 MindSpore 优势|特点 昇思 MindSpore 不足 官方生态学习地址 初识MindSpore 昇思 MindSpore 是什么&#xff1f; 昇思MindSpore 是全场景深度学习架构&#xff0c;为开发者提供了全…

女生学计算机好不好?感觉计算机分有点高……?

众所周知&#xff0c;在国内的高校里&#xff0c;计算机专业的女生是非常少的&#xff0c;很多小班30人左右&#xff0c;但是每个班女生人数只有个位数。这就给很多人一个感觉&#xff0c;是不是女生天生就不适合学这个东西呢&#xff1f;女生是不是也应该放弃呢&#xff1f;当…

常见算法和Lambda

常见算法和Lambda 文章目录 常见算法和Lambda常见算法查找算法基本查找&#xff08;顺序查找&#xff09;二分查找/折半查找插值查找斐波那契查找分块查找扩展的分块查找&#xff08;无规律的数据&#xff09; 常见排序算法冒泡排序选择排序插入排序快速排序递归快速排序 Array…

SpringBoot新手快速入门系列教程二:MySql5.7.44的免安装版本下载和配置,以及简单的Mysql生存指令指南。

我们要如何选择MySql 目前主流的Mysql有5.0、8.0、9.0 主要区别 MySQL 5.0 发布年份&#xff1a;2005年特性&#xff1a; 基础事务支持存储过程、触发器、视图基础存储引擎&#xff08;如MyISAM、InnoDB&#xff09;外键支持基本的全文搜索性能和扩展性&#xff1a; 相对较…

2024年江苏省研究生数学建模竞赛B题火箭烟幕弹运用策略优化论文和代码分析

经过不懈的努力&#xff0c; 2024年江苏省研究生数学建模竞赛B题火箭烟幕弹运用策略优化论文和代码已完成&#xff0c;代码为B题全部问题的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建立和求解、问题2模…

[学习笔记]SQL学习笔记(连载中。。。)

学习视频&#xff1a;【数据库】SQL 3小时快速入门 #数据库教程 #SQL教程 #MySQL教程 #database#Python连接数据库 目录 1.SQL的基础知识1.1.表(table)和键(key)1.2.外键、联合主键 2.MySQL安装&#xff08;略&#xff0c;请自行参考视频&#xff09;3.基本的MySQL语法3.1.规…

进程控制-fork函数

一个进程&#xff0c;包括代码、数据和分配给进程的资源。 fork &#xff08;&#xff09;函数通过系统调用创建一个与原来进程几乎完全相同的进程&#xff0c;也就是两个进程可以做完全相同的事&#xff0c;但如果初始参数或者传入的变量不同&#xff0c;两个进程也可以做不同…

DatawhaleAI夏令营2024 Task2

#AI夏令营 #Datawhale #夏令营 赛题解析一、Baseline详解1.1 环境配置1.2 数据处理任务理解2.3 prompt设计2.4 数据抽取 二、完整代码总结 赛题解析 赛事背景 在数字化时代&#xff0c;企业积累了大量对话数据&#xff0c;这些数据不仅是交流记录&#xff0c;还隐藏着宝贵的信…

【鸿蒙学习笔记】@Link装饰器:父子双向同步

官方文档&#xff1a;Link装饰器&#xff1a;父子双向同步 目录标题 [Q&A] Link装饰器作用 [Q&A] Link装饰器特点样例&#xff1a;简单类型样例&#xff1a;数组类型样例&#xff1a;Map类型样例&#xff1a;Set类型样例&#xff1a;联合类型 [Q&A] Link装饰器作用…

信号与系统-实验6-离散时间系统的 Z 域分析

一、实验目的 1、掌握 z 变换及其性质&#xff1b;了解常用序列的 z 变换、逆 z 变换&#xff1b; 2、掌握利用 MATLAB 的符号运算实现 z 变换&#xff1b; 3、掌握利用 MATLAB 绘制离散系统零、极点图的方法&#xff1b; 4、掌握利用 MATLAB 分析离散系统零、极点的方法&a…

MySQL基础篇(二)字符集以及校验规则

在MySQL基础篇&#xff08;一&#xff09;中&#xff0c;我们知道了如何创建数据库&#xff0c;这篇文章带大家了解创建的一些细节。 红色框&#xff1a;可省略&#xff0c;作用如果存在相同的数据库名称&#xff0c;就不会再创建&#xff0c;反之&#xff0c;创建。 蓝色框&…

uniapp 封装请求

新建request文件夹 下新建index.js 和index.js 或者创建units文件放入index.js 和api文件夹放入index.js(api.js)//看公司规范 1. index.js // 全局请求封装 // const base_url http://localhost:8080/devapi var base_url process.env.NODE_ENV development ? http://…

可用于多个微信管理的神器

以下仅是多微信聚合聊天管理界面&#xff1a; 可以在一个页面上同时收发多个微信的消息&#xff0c;可以添加好友&#xff0c;通过好友请求。 可以修改昵称&#xff0c;不受字数限制。 可以将常用图片&#xff0c;文件等放入素材库&#xff0c;方便聊天时查找和发送。 可以设置…

搜索旋转数组

题目链接 搜索旋转数组 题目描述 注意点 数组已被旋转过很多次数组元素原先是按升序排列的若有多个相同元素&#xff0c;返回索引值最小的一个 解答思路 首先需要知道的是&#xff0c;本题数组中的旋转多次只是将头部的某些元素移动到尾部&#xff0c;所以不论怎么旋转&am…