当前位置: 首页 > article >正文

WebSocket 从入门到进阶实战

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

聊天系统是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; // 滚动到底部}// 页面加载时连接 WebSocketwindow.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 {@Beanpublic 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<>());@OnOpenpublic void onOpen(Session session) {sessions.add(session);log.info("新用户连接: " + session.getId());sendMessageToAll("系统通知: 有新用户加入了聊天室!");}@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自用户的消息: " + message);sendMessageToAll(message);}@OnClosepublic void onClose(Session session) {sessions.remove(session);log.info("用户断开连接: " + session.getId());sendMessageToAll("系统通知: 有用户离开了聊天室!");}@OnErrorpublic 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 或 “码出精彩” ,和我一起探讨软件研发的那些事。

相关文章:

WebSocket 从入门到进阶实战

好记忆不如烂笔头&#xff0c;能记下点东西&#xff0c;就记下点&#xff0c;有时间拿出来看看&#xff0c;也会发觉不一样的感受. 聊天系统是WebSocket的最佳实践&#xff0c;以下是使用WebSocket技术实现的一个聊天系统的关键代码&#xff0c;可以通过这些关键代码&#xff…...

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

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

Linux 正则表达式 扩展正则表达式 gawk

什么是正则表达式 正则表达式是我们所定义的模式模板&#xff08;pattern template&#xff09;&#xff0c;Linux工具用它来过滤文本。Linux工具&#xff08;比如sed编辑器或gawk程序&#xff09;能够在处理数据时&#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;问题原因是…...

探秘鸿蒙 HarmonyOS NEXT:Navigation 组件的全面解析

鸿蒙 ArkTS 语言中 Navigation 组件的全面解析 一、引言 本文章基于HarmonyOS NEXT操作系统&#xff0c;API12以上的版本。 在鸿蒙应用开发中&#xff0c;ArkTS 作为一种简洁、高效的开发语言&#xff0c;为开发者提供了丰富的组件库。其中&#xff0c;Navigation 组件在构建…...

订单导入(常见问题和sql)

1.印章取行,有几行取几行 union select PARAM07 name, case when regexp_count(PO_PARAM_20, chr(10)) > 0 then substr(PO_PARAM_20, 0, instr(PO_PARAM_20, chr(10)) - 1) else PO_PARAM_20 end value,PO_ID …...

PyTorch中diag_embed和transpose函数使用详解

torch.diag_embed 是 PyTorch 中用于将一个向量&#xff08;或批量向量&#xff09;**嵌入为对角矩阵&#xff08;或批量对角矩阵&#xff09;**的函数。它常用于图神经网络&#xff08;GNN&#xff09;或线性代数中生成对角矩阵。 函数原型 torch.diag_embed(input, offset0,…...

算法分析与设计实验:找零钱问题的贪心算法与动态规划解决方案

在计算机科学中&#xff0c;贪心算法和动态规划是两种常用的算法设计策略。本文将通过一个经典的找零钱问题&#xff0c;详细讲解这两种算法的实现和应用。我们将会提供完整的C代码&#xff0c;并对代码进行详细解释&#xff0c;帮助读者更好地理解和掌握这两种算法。 问题描述…...

制作 MacOS系统 の Heic动态壁纸

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

大数据 笔记

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

js中encodeURIComponent函数使用场景

encodeURIComponent 是 JavaScript 中的一个内置函数&#xff0c;它的作用是&#xff1a; 将字符串编码为可以安全放入 URL 的形式。 ✅ 为什么需要它&#xff1f; URL 中有一些字符是有特殊意义的&#xff0c;比如&#xff1a; ? 用来开始查询参数 & 分隔多个参数 连接…...

iOS工厂模式

iOS工厂模式 文章目录 iOS工厂模式简单工厂模式&#xff08;Simple Factory&#xff09;工厂方法模式&#xff08;Factory Method&#xff09;抽象工厂模式&#xff08;Abstract Factory&#xff09;三种模式对比 简单工厂模式&#xff08;Simple Factory&#xff09; 定义&am…...

【数据库】-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;目前…...

【缓存】JAVA本地缓存推荐Caffeine和Guava

&#x1f31f; 引言 在软件开发过程中&#xff0c;缓存是提升系统性能的常用手段。对于基础场景&#xff0c;直接使用 Java集合框架&#xff08;如Map/Set/List&#xff09;即可满足需求。然而&#xff0c;当面对更复杂的缓存场景时&#xff1a; 需要支持多种过期策略&#x…...

Prometheus的服务命令和配置文件

一、Prometheus的服务端命令和启动方式 1.服务端命令&#xff08;具体详情可以--help查看&#xff09; --config.file“prometheus.yml”指定配置文件&#xff0c;默认是当前目录下的prometheus.yml--web.listen-address"0.0.0.0:9090"web页面的地址与端口&#xf…...

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

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

前端JavaScript-嵌套事件

点击 如果在多层嵌套中&#xff0c;对每层都设置事件监视器&#xff0c;试试看 <!DOCTYPE html> <html lang"cn"> <body><div id"container"><button>点我&#xff01;</button></div><pre id"output…...

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;…...

Java设计模式之组合模式:从入门到精通(保姆级教程)

文章目录 1. 组合模式概述1.1 专业定义1.2 通俗解释1.3 模式结构2. 组合模式详细解析2.1 模式优缺点2.2 适用场景3. 组合模式实现详解3.1 基础实现3.2 代码解析4. 组合模式进阶应用4.1 透明式 vs 安全式组合模式4.2 组合模式与递归4.3 组合模式与迭代器5. 组合模式在实际开发中…...

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 是…...

从零开始学习three.js(21):一文详解three.js中的矩阵Matrix和向量Vector

一、三维世界的数学基石 在Three.js的三维世界里&#xff0c;所有视觉效果的实现都建立在严密的数学基础之上。其中向量&#xff08;Vector&#xff09; 和矩阵&#xff08;Matrix&#xff09; 是最核心的数学工具&#xff0c;它们就像构建数字宇宙的原子与分子&#xff0c;支…...

应届本科生简历制作指南

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