【SpringBoot】SpringBoot:构建实时聊天应用
文章目录
- 引言
- 项目初始化
- 添加依赖
- 配置WebSocket
- 创建WebSocket配置类
- 创建WebSocket处理器
- 创建前端页面
- 创建聊天页面
- 测试与部署
- 示例:编写单元测试
- 部署
- 扩展功能
- 用户身份验证
- 消息持久化
- 群组聊天
- 结论

引言
随着实时通信技术的快速发展,聊天应用在现代Web和移动应用中变得越来越重要。从简单的客服聊天到复杂的团队协作工具,实时通信都扮演着关键角色。SpringBoot结合WebSocket技术,能够高效地构建实时聊天应用。本文将详细介绍如何使用SpringBoot和WebSocket来构建一个实时聊天应用,并讨论相关的最佳实践。
项目初始化
首先,我们需要创建一个SpringBoot项目,并添加WebSocket相关的依赖项。可以通过Spring Initializr快速生成项目。
添加依赖
在pom.xml
中添加以下依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置WebSocket
创建WebSocket配置类
创建一个配置类,用于配置WebSocket连接。
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 {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new ChatWebSocketHandler(), "/chat").setAllowedOrigins("*");}
}
创建WebSocket处理器
创建一个处理WebSocket消息的处理器类。
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;public class ChatWebSocketHandler extends TextWebSocketHandler {private List<WebSocketSession> sessions = new ArrayList<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.add(session);}@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {for (WebSocketSession webSocketSession : sessions) {webSocketSession.sendMessage(new TextMessage(message.getPayload()));}}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {sessions.remove(session);}
}
创建前端页面
创建聊天页面
使用Thymeleaf创建一个简单的聊天页面。在src/main/resources/templates
目录下创建一个chat.html
文件:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Chat Room</title><script>var socket;function connect() {socket = new WebSocket("ws://localhost:8080/chat");socket.onmessage = function(event) {var messages = document.getElementById("messages");var message = document.createElement("p");message.appendChild(document.createTextNode(event.data));messages.appendChild(message);};}function sendMessage() {var input = document.getElementById("messageInput");socket.send(input.value);input.value = '';}</script>
</head>
<body onload="connect()"><h1>Chat Room</h1><div id="messages"></div><input type="text" id="messageInput" placeholder="Enter message" onkeydown="if (event.key === 'Enter') sendMessage()"/><button onclick="sendMessage()">Send</button>
</body>
</html>
测试与部署
在完成实时聊天功能的开发后,应该进行充分的测试,确保所有功能都能正常工作。可以使用JUnit和MockMVC进行单元测试和集成测试。
示例:编写单元测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;@SpringBootTest
@AutoConfigureMockMvc
public class ChatApplicationTests {@Autowiredprivate MockMvc mockMvc;@Testpublic void testChatPage() throws Exception {mockMvc.perform(get("/chat")).andExpect(status().isOk()).andExpect(content().string(org.hamcrest.Matchers.containsString("Chat Room")));}
}
通过这种方式,可以确保应用的各个部分在开发过程中得到充分的测试,减少上线后的问题。
部署
SpringBoot应用可以打包成可执行的JAR文件,方便部署。通过mvn package
命令,可以生成一个包含所有依赖的JAR文件。
mvn package
java -jar target/demo-0.0.1-SNAPSHOT.jar
这种打包方式使得SpringBoot应用的部署变得非常简单,不再需要复杂的服务器配置。
扩展功能
在基本的实时聊天功能基础上,可以进一步扩展功能,使其更加完善和实用。例如:
- 用户身份验证:可以集成Spring Security,实现用户登录和身份验证。
- 消息持久化:将聊天消息存储到数据库中,以便后续查询和分析。
- 群组聊天:实现多个聊天室,每个聊天室有独立的聊天内容。
- 消息通知:集成WebSocket通知功能,当有新消息时,向用户发送通知。
用户身份验证
可以使用Spring Security实现用户身份验证。在前面的示例中,我们已经配置了Spring Security。在此基础上,可以实现用户登录和权限控制。
消息持久化
为了实现消息持久化,可以将聊天消息存储到数据库中。首先,创建一个消息实体类和消息存储库:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;@Entity
public class ChatMessage {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String sender;private String content;// getters and setters
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;@Repository
public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {
}
然后,在WebSocket处理器中保存消息:
import org.springframework.beans.factory.annotation.Autowired;public class ChatWebSocketHandler extends TextWebSocketHandler {@Autowiredprivate ChatMessageRepository chatMessageRepository;@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {ChatMessage chatMessage = new ChatMessage();chatMessage.setSender(session.getId());chatMessage.setContent(message.getPayload());chatMessageRepository.save(chatMessage);for (WebSocketSession webSocketSession : sessions) {webSocketSession.sendMessage(new TextMessage(message.getPayload()));}}
}
群组聊天
为了实现群组聊天,可以为每个群组创建一个独立的WebSocket端点。用户可以选择加入不同的群组聊天。
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new ChatWebSocketHandler(), "/chat/{group}").setAllowedOrigins("*");}
}
结论
通过本文的介绍,我们了解了如何使用SpringBoot和WebSocket实现实时聊天应用。从项目初始化、WebSocket配置、前端页面创建,到消息持久化和功能扩展,SpringBoot提供了一系列强大的工具和框架,帮助开发者高效地构建现代化的实时聊天应用。希望这篇文章能够帮助开发者更好地理解和使用SpringBoot,在实际项目中实现实时通信的目标。
相关文章:

【SpringBoot】SpringBoot:构建实时聊天应用
文章目录 引言项目初始化添加依赖 配置WebSocket创建WebSocket配置类创建WebSocket处理器 创建前端页面创建聊天页面 测试与部署示例:编写单元测试 部署扩展功能用户身份验证消息持久化群组聊天 结论 引言 随着实时通信技术的快速发展,聊天应用在现代We…...

基于Matlab的车牌识别停车场出入库计时计费管理系统(含GUI界面)【W6】
简介: 在当今城市化进程加快的环境下,停车管理成为了一个日益重要和复杂的问题。城市中的停车资源有限,如何高效利用和管理这些资源,不仅关乎市民出行便利性,也涉及到城市交通拥堵、环境污染等诸多问题的解决。 传统的…...

大众点评js逆向过程(未完)
相关链接 1、控制流平坦化进行AST 解析 AST网址 2、JS进制转换(Function.prototype.call) 1、断点调试mtgsig参数 这里mtgsig已经被拼到url中 2、进入后mtgsig已经计算完, ir he(this[b(4326)], !1), 就是加密函数 
龙迅LT9611UXC 2 PORT MIPIDSI/CSI转HDMI 2.1,支持音频IIS/SPDIF输入,支持标准4K60HZ输出
龙迅LT9611UXC描述: LT9611UXC是一个高性能的MIPI DSI/CSI到HDMI2.0转换器。MIPI DSI/CSI输入具有可配置的单端口或双端口,1高速时钟通道和1~4高速数据通道,最大2Gbps/通道,可支持高达16Gbps的总带宽。LT9611UXC支持突发模式DSI视…...

红黑树(C++)
文章目录 写在前面1. 红黑树的概念及性质1. 1 红黑树的概念1. 2 红黑树的性质 2. 红黑树节点的定义3. 红黑树的插入3.1 按照二叉搜索的树规则插入新节点3.2 检测新节点插入后,红黑树的性质是否造到破坏 4.红黑树的删除5.红黑树的验证6.源码 写在前面 在上篇文章中&…...

PyCharm设置不默认打开上次的项目
第一步 第二步 第三步 测试...

Eureka到Nacos迁移实战:解决配置冲突与启动异常
问题:Eureka到Nacos迁移实战:解决配置冲突与启动异常 在进行微服务架构升级,特别是注册中心从Eureka转向Nacos的过程中,我遇到了一个典型的技术挑战。目标是为了减少因配置变更导致的服务重启频率,我决定拥抱Nacos以其…...
k8s 小技巧: 查看 Pod 上运行的容器
目录 1. 示例 Pod 的定义文件2. kubectl describe pod(推荐)3. kubectl get pod3.1 json 格式3.2 yaml 格式 4. 其他操作 1. 示例 Pod 的定义文件 # 文章中所用 pod 的 yaml 定义文件, multi-container.yaml apiVersion: v1 kind: Pod metad…...

【Git】基础操作
初识Git 版本控制的方式: 集中式版本控制工具:版本库是集中存放在中央服务器的,team里每个人work时从中央服务器下载代码,是必须联网才能工作,局域网或者互联网。个人修改之后要提交到中央版本库 例如:SVM和…...

Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)
上次介绍了:Linux:基础IO(一.C语言文件接口与系统调用、默认打开的文件流、详解文件描述符与dup2系统调用) 文章目录 1.缓冲区1.1概念1.2作用与意义 2.语言级别的缓冲区2.1刷新策略2.2具体在哪里2.3支持格式化 3.自己来模拟一下缓…...
事件传播机制 与 责任链模式
1、基本概念 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,将请求沿着处理链传递,直到有一个对象能够处理为止。 2、实现的模块有: Handler(处理者):定义一个…...

uniapp 展示地图,并获取当前位置信息(精确位置)
使用uniapp 提供的map标签 <map :keymapIndex class"container" :latitude"latitude" :longitude"longitude" ></map> 页面初始化的时候,获取当前的位置信息 created() {let that thisuni.getLocation({type: gcj02…...
Autosar实践——诊断配置(DaVinci Configuration)
文章目录 一、制作诊断数据库文件(cdd文件)二、导入诊断数据库文件并修复模块生成的问题三、创建SWC CS接口Service Ports四、创建Service Runnable五、关联SWC和DCM/DEM模块六、RTE代码编写22服务2E服务31服务DTC Set/Get关联文章列表: Autosar-软件架构 Autosar诊断-简介和…...

植物大战僵尸杂交版全新版v2.1解决全屏问题
文章目录 🚋一、植物大战僵尸杂交版❤️1. 游戏介绍💥2. 如何下载《植物大战僵尸杂交版》 🚀二、解决最新2.1版的全屏问题🌈三、画质增强以及减少闪退 🚋一、植物大战僵尸杂交版 《植物大战僵尸杂交版》是一款在原版《…...

【code-server】Code-Server 安装部署
Code-Server 安装部署 1.环境准备 可以参考 https://coder.com/docs/code-server/install code-server的安装流程进行安装,主机环境是 Centos7 建议使用 docker 方式进行安装,可能会出现如下报错,需要升级 GNC 的版本,由于影响较…...
博客摘录「 YOLOv5模型剪枝压缩」2024年5月11日
添加L1正则来约束BN层系数 语义边缘检测和语义分割的关系调研结果为,语义信息可以用来增强语义分割的效果,也有一定的优点和采用理由,但此类论文的数量并不是很多,语义分割的多数方法还是使用深度学习直接做像素分类。在对比两者…...
HttpSecurity
这是Spring Security提供的配置类, 用户保护基于HTTP的请求 ,通过HttpSecurity可以设置各种安全设置{认证,授权,CSRF保护,会话管理,异常处理} 主要功能和配置: 1.认证配置: 配置登录和登出功能,指定登录页面、登录处理 URL、成功和失败处理器等。配置认证方式,如表单登录、…...
Mysql union语句
开源项目SDK:https://github.com/mingyang66/spring-parent 个人文档:https://mingyang66.github.io/raccoon-docs/#/ mysql union操作符用于连接两个以上的select语句的结果组合到一个结果集,并去除重复的行,每个select语句的雷叔…...

MySQL之高级特性(四)
高级特性 查询缓存 什么情况下查询缓存能发挥作用 并不是什么情况下查询缓存都会提高系统性能的。缓存和失效都会带来额外的消耗,所以只有当缓存带来的资源节约大于本身的资源消耗时才会给系统带来性能提升。这跟具体的服务器压力模型有关。理论上,可…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙
WebGL:在浏览器中解锁3D世界的魔法钥匙 引言:网页的边界正在消失 在数字化浪潮的推动下,网页早已不再是静态信息的展示窗口。如今,我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室,甚至沉浸式的V…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...