Vue+TypeScript+SpringBoot的WebSocket基础教学

news2024/12/26 13:05:48

成品图: 

 对WebSocket的理解(在使用之前建议先了解Tcp,三次握手,四次挥手 ):

        首先页面与WebSocket建立连接、向WebSocket发送信息、后端WebSocket向所有连接上WebSoket的客户端发送当前信息。

推荐浏览网站:WebSocket 是什么?你需要知道的一切

第一步:在后端引入WebSocket依赖 

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

第二步:在后端配置WebSocket 

package cn.ryanfan.virtulab_back.config;

import cn.ryanfan.virtulab_back.websocket.ChatHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

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

第三步:建立WebSocket自定义支持 

package cn.ryanfan.virtulab_back.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.ArrayList;
import java.util.List;
@Slf4j
public class ChatHandler extends TextWebSocketHandler {

    private final List<WebSocketSession> sessions = new ArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        for (WebSocketSession s : sessions) {
            if (s.isOpen()) {
                s.sendMessage(message);
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }
}

 第四步:在前端开启WebSocket通信

<template>
  <div class="chat-container">
    <div class="chat-header">
      <h3>在线聊天</h3>
    </div>

    <div class="chat-messages">
      <!-- 显示消息列表 -->
      <div
          v-for="(message, index) in messages"
          :key="index"
          class="message-item"
          :class="{'my-message': message.sender === currentUser}"
      >
        <strong>{{ message.sender }}:</strong>
        <div class="message-content">{{ message.content }}</div>
      </div>
    </div>

    <div class="chat-input">
      <input
          v-model="newMessage"
          @keyup.enter="sendMessage"
          type="text"
          placeholder="输入消息"
          class="message-input"
      />
      <button @click="sendMessage" class="send-button">发送</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

interface Message {
  sender: string;
  content: string;
}

// 消息列表
const messages = ref<Message[]>([]);

// 当前用户输入的消息
const newMessage = ref('');

// 假设的发送方
const currentUser = 'User1';

// WebSocket 对象
let socket: WebSocket | null = null;

// 连接 WebSocket,并处理接收和发送消息的逻辑
const connectWebSocket = () => {
  socket = new WebSocket('ws://localhost:8667/VirtuLab_back/chat'); // 连接到后端 WebSocket
  // WebSocket 打开时触发
  socket.onopen = () => {
    console.log('WebSocket 连接已建立');
  };

  // 接收 WebSocket 消息时触发
  socket.onmessage = (event: MessageEvent) => {
    const data = JSON.parse(event.data); // 假设收到的消息是 JSON 格式
    console.log('WebSocket 对话已建立');
    console.log(data)
    messages.value.push({ sender: data.sender, content: data.content });
  };

  // WebSocket 关闭时触发
  socket.onclose = () => {
    console.log('WebSocket 连接已关闭');
  };

  // WebSocket 出现错误时触发
  socket.onerror = (error) => {
    console.error('WebSocket 错误:', error);
  };
};

// 发送消息
const sendMessage = () => {
  if (newMessage.value.trim() !== '' && socket && socket.readyState === WebSocket.OPEN) {
    const message = {
      sender: currentUser,
      content: newMessage.value
    };
    socket.send(JSON.stringify(message)); // 发送 JSON 格式的消息到服务器
    newMessage.value = ''; // 清空输入框
  }
};

// 当组件挂载时连接 WebSocket
onMounted(() => {
  connectWebSocket();
});

// 当组件卸载时关闭 WebSocket
onUnmounted(() => {
  if (socket) {
    socket.close();
  }
});
</script>

<style scoped>
.chat-container {
  width: 400px;
  border: 1px solid #ccc;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 500px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  background-color: #ffffff;
}

.chat-header {
  padding: 15px;
  background-color: #007bff;
  color: white;
  text-align: center;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
  font-weight: bold;
}

.chat-messages {
  flex: 1;
  padding: 15px;
  overflow-y: auto;
  background-color: #f9f9f9;
  border-bottom: 1px solid #ddd;
}

.message-item {
  margin-bottom: 10px;
  padding: 10px;
  border-radius: 8px;
}

.my-message {
  background-color: #007bff;
  color: white;
  align-self: flex-end;
}

.message-content {
  margin-top: 5px;
}

.chat-input {
  display: flex;
  padding: 10px;
  background-color: #f1f1f1;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}

.message-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin-right: 10px;
  transition: border-color 0.3s;
}

.message-input:focus {
  border-color: #007bff;
  outline: none;
}

.send-button {
  padding: 10px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.send-button:hover {
  background-color: #0056b3;
}
</style>

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

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

相关文章

燕山大学23级经济管理学院 10.18 C语言作业

燕山大学23级经济管理学院 10.18 C语言作业 文章目录 燕山大学23级经济管理学院 10.18 C语言作业1C语言的基本数据类型主要包括以下几种&#xff1a;为什么设计数据类型&#xff1f;数据类型与知识体系的对应使用数据类型时需要考虑的因素 21. 逻辑运算符2. 真值表3. 硬件实现4…

设计模式(UML图、类之间关系、设计原则)

目录 一.类的UML图 1.类的UML图 2.类之间的关系 2.1 继承关系&#xff1a; 2.2关联关系 2.2.1单项关联 2.2.2双向关联 2.2.3自关联 2.3聚合关系 2.4组合模式 2.5依赖关系 二、设计三原则 2.1单一职责原则 2.2开放封闭原则 2.3依赖倒转原则 一.类的UML图 1.类的…

考研篇——数据结构王道3.2.2_队列的顺序实现

目录 1.实现方式说明2.代码实现2.12.1.1 代码12.1.2 代码22.1.3 代码3 2.22.2.1 代码42.2.5 代码52.2.6 代码6 总结 1.实现方式说明 多在选择题中考察 队尾指针&#xff08;rear&#xff09;有两种指向方式&#xff1a; 队尾指针指向队尾元素的位置&#xff0c;队尾指针指向…

9个3D直播场景推荐

在科技日新月异的今天&#xff0c;3D直播技术正逐步渗透至文旅领域&#xff0c;为游客带来前所未有的沉浸式体验。以下是vLive虚拟直播九个精心推荐的文旅3D直播场景&#xff0c;它们不仅展现了各地独特的文化魅力&#xff0c;还通过高科技手段让游客仿佛穿越时空&#xff0c;身…

ArcGIS应用指南:多尺度渔网创建

在GIS中&#xff0c;创建渔网矢量文件是GIS中的一项常见任务&#xff0c;通过将研究区域划分为规则的网格&#xff0c;可以更精细地分析和管理城市空间数据。本文以厦门市行政区为例&#xff0c;详细介绍了如何创建不同尺度的渔网矢量网格&#xff0c;以适应不同区域的发展特点…

代码随想录算法训练营第46期Day35

leetcode.452.用最少数量的箭射爆气球 class Solution { public:static bool cmp(const vector<int>& a,const vector<int>& b){//对Xend进行排序return a[1]<b[1]; } //这个题比较好贪&#xff0c;我们每次射只需要射Xend就可以了&#xff0c;然后用此…

OpenCL内存模型

OpenCL将内存划分成主机内存和设备内存。主机内存可在主机上使用&#xff0c;其并不在OpenCL的定义范围内。使用对应的OpenCL API可以进行主机和设备的数据传输&#xff0c;或者通过共享虚拟内存接口进行内存共享。而设备内存&#xff0c;指定是能在执行内核中使用的内存空间。…

什么是不同类型的微服务测试?

大家好&#xff0c;我是锋哥。今天分享关于【什么是不同类型的微服务测试&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; 什么是不同类型的微服务测试&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 微服务架构中的测试可以分为多种类…

【ROS2】构建导航工程

1、ROS小车组成 ROS小车由三大件组成:运动底盘、ROS主控、导航传感器。 1.1 运动底盘 运动底盘的硬件由车轮、电机(带编码器)、电机驱动器、STM32控制器、电池等组成。 涉及的知识点主要为:STM32单片机程序、机器人运动学分析 1)STM32单片机程序 单片机程序框架如下:…

在Linux命令行下载Google Drive大文件(解决Google Drive下载慢的问题)

文章目录 1、使用gdown命令2、复制链接3、替换为Linux下载链接 注意&#xff1a;在Linux命令行进行 1、使用gdown命令 wget只能下载小文件&#xff0c;大文件需要用到gdown pip install gdown# 如果不能够直接安装&#xff0c;使用以下命令 git clone https://github.com/wk…

基于Spring Boot + Vue程序员云书店系统设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

MySQL9.0安装教程zip手动安装(Windows)

本章教程&#xff0c;主要介绍如何在Windows上安装MySQL9.0&#xff0c;通过zip方式进行手动安装。 一、下载MySQL压缩包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 二、解压MySQL压缩包 将下载好的压缩包&#xff0c;进行解压缩&#xff0c;并且将…

要让AI(任何一款绘图AI)把一个己有风格的图片画到一个实物商品上的窍门

本教程适合midjourney, comfyui, stable diffusion 己有图片 希望生成效果 我们希望&#xff0c;在一个现实世界真实IPhone手机上可以有一个这样的小魔女作为一个手机的展示&#xff0c;同时手机处于开机状态&#xff0c;在手机的屏幕上有一个这样的戴帽子的穿蓝色小披风的小…

阿里Dataworks使用循环节点和赋值节点完成对mongodb分表数据同步

背景 需求将MongoDB数据入仓MaxCompute 环境说明 MongoDB 100个Collections&#xff1a;orders_1、orders_2、…、orders_100 前期准备 1、MongoDB数据源配置 需要先保证DW和MongoDB网络是能够联通的&#xff0c;需要现在集成任务中配置MongoDB的数据源信息。 具体可以查…

Java项目-基于springboot框架的学习选课系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

Linux基础命令(入门)

linux 用户 root 用户 一个特殊的管理帐户 也被称为超级用户 root已接近完整的系统控制 对系统损害几乎有无限的能力 除非必要,不要登录为 root 普通&#xff08; 非特权 &#xff09; 用户权限有限 造成损害的能力比较有限 linux的哲学思想&#xff08;优点&#xf…

vue3学习记录-组件通信

vue3学习记录-组件通信 1.父子组件通信2.兄弟组件传值2.1 以父组件为媒介2.2 发布订阅模式2.3 使用mitt2.3.1 全局使用2.3.2 局部使用 1.父子组件通信 父组件&#xff1a; <template>父组件原有的title:{{ title }}<p>---</p><com :title"title&qu…

jmeter使用文档

文章目录 一、安装使用1、下载2、bin/jmeter.properties介绍 二、windows使用1、微调&#xff08;1&#xff09;界面样式&#xff08;2&#xff09;修改语言 2、简单使用3、各组件详解&#xff08;1&#xff09;CSV 数据文件配置&#xff08;2&#xff09;BeanShell取样器 三、…

【Linux线程】Linux多线程实践:深入生产者消费者模型

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux多线程 &#x1f4d2;1. 生产者消费者模型&#x1f4dc;2. 基于BlockingQueue的生产者消…

BurpSuite渗透工具的简单使用

BurpSuite渗透工具 用Burp Suite修改请求 step1&#xff1a; 安装Burp Suite。官网链接&#xff1a;Burp Suite官网 step2&#xff1a; 设置代理 step3&#xff1a; 如果要拦截https请求&#xff0c;还需要在客户端安装证书 step4&#xff1a; 拦截到请求可以在Proxy ->…