WebSocket 从入门到进阶实战

news2025/5/23 23:23:45

好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.

聊天系统是WebSocket的最佳实践,以下是使用WebSocket技术实现的一个聊天系统的关键代码,可以通过这些关键代码,更加清晰的了解 WebSocket 在项目中的使用情况(本实战将以springboot框架进行展开)。

目录

一、前端代码(HTML + JavaScript)

前端页面:chat.html

二、Java 后端代码(Spring Boot)

1. 添加依赖

2. 配置 WebSocket

3. 创建 WebSocket 服务端类

4. 创建 Spring Boot 应用主类

三、异常处理和性能优化

1. 异常处理

2. 性能优化

四、运行和测试

五、总结


一、前端代码(HTML + JavaScript)

前端页面:chat.html
 
<!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;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #f4f4f4;
        }
        #chat-container {
            width: 80%;
            max-width: 600px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        #chat-header {
            background: #007bff;
            color: white;
            padding: 10px;
            text-align: center;
            font-size: 1.5em;
        }
        #chat-body {
            height: 300px;
            overflow-y: auto;
            padding: 10px;
            border-bottom: 1px solid #ddd;
        }
        #chat-footer {
            display: flex;
            padding: 10px;
        }
        #chat-footer input {
            flex: 1;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-right: 10px;
        }
        #chat-footer button {
            padding: 8px 16px;
            border: none;
            background: #007bff;
            color: white;
            border-radius: 4px;
            cursor: pointer;
        }
        #chat-footer button:hover {
            background: #0056b3;
        }
        .message {
            margin-bottom: 10px;
        }
        .message .username {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div id="chat-container">
        <div id="chat-header">实时聊天室</div>
        <div id="chat-body"></div>
        <div id="chat-footer">
            <input type="text" id="message-input" placeholder="输入消息...">
            <button onclick="sendMessage()">发送</button>
        </div>
    </div>

    <script>
        const chatBody = document.getElementById('chat-body');
        const messageInput = document.getElementById('message-input');
        let webSocket = null;

        // 连接 WebSocket 服务器
        function connect() {
            if ('WebSocket' in window) {
                webSocket = new WebSocket("ws://localhost:8080/chat");
                webSocket.onopen = function() {
                    console.log("已连接到服务器");
                };
                webSocket.onmessage = function(event) {
                    const message = JSON.parse(event.data);
                    displayMessage(message);
                };
                webSocket.onclose = function() {
                    console.log("连接已关闭");
                };
                webSocket.onerror = function(error) {
                    console.error("WebSocket 发生错误:", error);
                };
            } else {
                alert("您的浏览器不支持 WebSocket!");
            }
        }

        // 发送消息
        function sendMessage() {
            const messageText = messageInput.value.trim();
            if (messageText) {
                const message = {
                    username: "用户" + Math.floor(Math.random() * 100), // 模拟用户名
                    text: messageText
                };
                webSocket.send(JSON.stringify(message));
                messageInput.value = '';
            }
        }

        // 显示消息
        function displayMessage(message) {
            const messageElement = document.createElement('div');
            messageElement.classList.add('message');
            messageElement.innerHTML = `<span class="username">${message.username}:</span> ${message.text}`;
            chatBody.appendChild(messageElement);
            chatBody.scrollTop = chatBody.scrollHeight; // 滚动到底部
        }

        // 页面加载时连接 WebSocket
        window.onload = connect;
    </script>
</body>
</html>

二、Java 后端代码(Spring Boot)

1. 添加依赖

pom.xml 文件中添加 WebSocket 依赖:
 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2. 配置 WebSocket

创建一个配置类 WebSocketConfig
 

package com.example.websocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
3. 创建 WebSocket 服务端类

创建一个 WebSocket 服务端类 ChatServer
 

package com.example.websocket.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

@ServerEndpoint("/chat")
@Component
public class ChatServer {
    private static final Logger log = LoggerFactory.getLogger(ChatServer.class);
    private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());

    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
        log.info("新用户连接: " + session.getId());
        sendMessageToAll("系统通知: 有新用户加入了聊天室!");
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自用户的消息: " + message);
        sendMessageToAll(message);
    }

    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        log.info("用户断开连接: " + session.getId());
        sendMessageToAll("系统通知: 有用户离开了聊天室!");
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error("WebSocket 发生错误: " + throwable.getMessage());
        sessions.remove(session);
    }

    // 向所有用户发送消息
    private void sendMessageToAll(String message) {
        synchronized (sessions) {
            for (Session session : sessions) {
                if (session.isOpen()) {
                    try {
                        session.getBasicRemote().sendText(message);
                    } catch (IOException e) {
                        log.error("发送消息时发生错误: " + e.getMessage());
                    }
                }
            }
        }
    }
}
4. 创建 Spring Boot 应用主类

创建一个主类 ChatApplication

package com.example.websocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ChatApplication {
    public static void main(String[] args) {
        System.out.println("聊天系统正在启动");
        SpringApplication.run(ChatApplication.class, args);
        System.out.println("聊天系统启动完成");
    }
}

三、异常处理和性能优化

1. 异常处理
  • onError 方法中记录错误日志,并从会话集合中移除异常的会话。

  • 在发送消息时捕获 IOException,避免因单个会话异常导致整个应用崩溃。

2. 性能优化
  • 使用 CopyOnWriteArraySet 存储会话集合,确保线程安全。

  • 在发送消息时,通过同步块确保线程安全,避免并发问题。

四、运行和测试

  1. 启动后端服务:运行 ChatApplication 类启动 Spring Boot 应用。

  2. 打开前端页面:在浏览器中打开 chat.html 文件。

  3. 测试聊天功能:在多个浏览器窗口中打开 chat.html,输入消息并发送,观察消息是否实时同步到其他窗口。

五、总结

以上代码实现了一个简单的实时聊天系统,前端使用 HTML 和 JavaScript,后端使用 Spring Boot 和 WebSocket。代码中包含了异常处理和性能优化的措施,确保系统的稳定性和高效性。通过 WebSocket 的实时通信能力,用户可以即时发送和接收消息,提升用户体验。

关注我,带你了解更多IT知识
搜索codingba 或 “码出精彩” ,和我一起探讨软件研发的那些事。

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

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

相关文章

CSS:vertical-align用法以及布局小案例(较难)

文章目录 一、vertical-align说明二、布局案例 一、vertical-align说明 上面的文字介绍&#xff0c;估计大家也看不懂 二、布局案例

Java转Go日记(五十四):gin路由

1. 基本路由 gin 框架中采用的路由库是基于httprouter做的 地址为&#xff1a;https://github.com/julienschmidt/httprouter package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/", func(c …

【解决】自己的域名任何端口都访问不到,公网地址正常访问,服务器报错500。

一、问题描述 后端项目部署在服务器上&#xff0c;通过域名访问接口服务器报错500&#xff0c;通过浏览器访问域名的任何端口都是无法访问此网站。 但是通过公网地址访问是可以正常访问到的&#xff0c;感觉是域名出现了问题 二、解决过程 先说结论&#xff1a;问题原因是…

制作 MacOS系统 の Heic动态壁纸

了解动态桌面壁纸 当macOS 10.14发布后&#xff0c;会发现系统带有动态桌面壁纸&#xff0c;设置后&#xff0c;我们的桌面背景将随着一天从早上、到下午、再到晚上的推移而发生微妙的变化。 虽然有些软件也有类似的动态变化效果&#xff0c;但是在新系统中默认的HEIC格式的动…

大数据 笔记

kafka kafka作为消息队列为什么发送和消费消息这么快&#xff1f; 消息分区&#xff1a;不受单台服务器的限制&#xff0c;可以不受限的处理更多的数据顺序读写&#xff1a;磁盘顺序读写&#xff0c;提升读写效率页缓存&#xff1a;把磁盘中的数据缓存到内存中&#xff0c;把…

【数据库】-1 mysql 的安装

文章目录 1、mysql数据库1.1 mysql数据库的简要介绍 2、mysql数据库的安装2.1 centos安装2.2 ubuntu安装 1、mysql数据库 1.1 mysql数据库的简要介绍 MySQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典MySQL AB公司开发&#xff0c;目前…

物流项目第五期(运费计算实现、责任链设计模式运用)

前四期&#xff1a; 物流项目第一期&#xff08;登录业务&#xff09;-CSDN博客 物流项目第二期&#xff08;用户端登录与双token三验证&#xff09;-CSDN博客 物流项目第三期&#xff08;统一网关、工厂模式运用&#xff09;-CSDN博客 物流项目第四期&#xff08;运费模板列…

X 下载器 2.1.42 | 国外媒体下载工具 网页视频嗅探下载

X 下载器让你能够轻松地从社交应用如Facebook、Instagram、TikTok等下载视频和图片。通过内置浏览器访问网站&#xff0c;它能自动检测视频和图片&#xff0c;只需点击下载按钮即可完成下载。去除广告&#xff0c;解锁本地会员&#xff0c;享受无广告打扰的下载体验。 大小&am…

STM32 CAN CANAerospace

STM32的CAN模块对接CANAerospace 刚开始报错如下. 设备开机后整个CAN消息就不发了. USB_CAN调试器报错如下. index time Name ID Type Format Len Data00000001 000.000.000 Event 总线错误 DATA STANDARD 8 接收过程错误-格…

完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取

1 简介 为了有效地利用雾状冰生长的物理现象&#xff0c;最近开发了一种优化算法——雾状优化算法&#xff08;RIME&#xff09;。它模拟硬雾状和软雾状过程&#xff0c;构建硬雾状穿刺和软雾状搜索机制。在本研究中&#xff0c;引入了一种增强版本&#xff0c;称为修改的RIME…

服务器安装xfce桌面环境并通过浏览器操控

最近需要运行某个浏览器的脚本&#xff0c;但是服务器没有桌面环境&#xff0c;无法使用&#xff0c;遂找到了KasmVNC&#xff0c;并配合xfce实现低占用的桌面环境&#xff0c;可以直接使用浏览器进行操作 本文基于雨云——新一代云服务提供商的Debian11服务器操作&#xff0c;…

Oracle 创建外部表

找别人要一下数据&#xff0c;但是他发来一个 xxx.csv 文件&#xff0c;怎么办&#xff1f; 1、使用视图化工具导入 使用导入工具导入&#xff0c;如 DBeaver&#xff0c;右击要导入的表&#xff0c;选择导入数据。 选择对应的 csv 文件&#xff0c;下一步就行了&#xff08;如…

大语言模型 17 - MCP Model Context Protocol 介绍对比分析 基本环境配置

MCP 基本介绍 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一种开放协议&#xff0c;旨在标准化应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…

【软考向】Chapter 9 数据库技术基础

基本概念数据库的三级模式结构 数据模型E-R 模型关系模型各种键完整性约束 关系代数5 种基本的关系代数运算&#xff1a;并、差、笛卡儿积、投影和选择扩展的关系代数运算&#xff1a;交(Intersection)、连接(Join)、除(Division)、广义投影(Generalized Projection)、外连接(O…

实战:Dify智能体+Java=自动化运营工具!

我们在运营某个圈子的时候&#xff0c;可能每天都要将这个圈子的“热门新闻”发送到朋友圈或聊天群里&#xff0c;但依靠传统的实现手段非常耗时耗力&#xff0c;我们通常要先收集热门新闻&#xff0c;再组装要新闻内容&#xff0c;再根据内容设计海报等。 那怎么才能简化并高…

STM32单片机GUI系统1 GUI基本内容

目录 一、GUI简介 1、emWin 2、LVGL (Light and Versatile Graphics Library) 3、TouchGFX 4、Qt for Embedded 5、特性对比总结 二、LVGL移植要求 三、优化LVGL运行效果方法 四、LVGL系统文件 一、GUI简介 在嵌入式系统中&#xff0c;emWin、LVGL、TouchGFX 和 Qt 是…

应届本科生简历制作指南

一、找一个专业的简历模板 首先&#xff0c;你需要访问 Overleaf 的官方网站&#xff0c;也就是Overleaf, Online LaTeX Editor&#xff0c;进入页面后&#xff0c;点击注册按钮&#xff0c;按照提示填写相关信息来创建一个属于自己的账号&#xff0c;通常需要填写用户名、邮箱…

PyTorch可视化工具——使用Visdom进行深度学习可视化

文章目录 前置环境Visdom安装并启动VisdomVisdom图形APIVisdom静态更新API详解通用参数说明使用示例Visdom动态更新API详解1. 使用updateappend参数2. ~~使用vis.updateTrace方法~~3. 完整训练监控示例 Visdom可视化操作散点图plot.scatter()散点图案例线性图vis.line()vis.lin…

企业级爬虫进阶开发指南

企业级爬虫进阶开发指南 一、分布式任务调度系统的深度设计 1.1 架构设计原理 图表 1.2 核心代码实现与注释 分布式锁服务 # distributed_lock.py import redis import timeclass DistributedLock:def __init__(self, redis_conn):self.redis = redis_connself.lock_key = …

网络安全-等级保护(等保) 2-7 GB/T 25058—2019 《信息安全技术 网络安全等级保护实施指南》-2019-08-30发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…