赞
踩
由于心血来潮想要做个聊天室项目 ,但是仔细找了一下相关教程,却发现这么多的WebSocket教程里面,很多都没有介绍详细,代码都有所残缺,所以这次带来一个比较完整得使用WebSocket的项目。
目录
一、前端框架,Vue + elementUI组件 +JsCookie
1.用户交流
新建一个vue项目
引入以下组件与依赖
npm i element-ui -S
npm install js-cookie
创建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 {
-
- @Override
- public 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<>());
-
- @Override
- public void afterConnectionEstablished(WebSocketSession session) throws Exception {
- sessions.add(session);
- broadcast("欢迎新的小伙伴加入");
- }
-
- @Override
- protected 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();
- }
- });
- }
-
- @Override
- public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
- sessions.remove(session);
-
- }
- }
后端启动:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。