简易聊天室项目(本地部署)

news/2025/3/28 9:05:46/文章来源:https://www.cnblogs.com/zhuang66/p/18791721

二、IDEA开发

1.创建新的空项目

file->project struture->+->new module

点击next,选取依赖


创建成功后,先将依赖下载(右上角会有一个小的m图标,点击就可以)

2.创建文件
先创建三个文件ChatHandler,WebSocketConfig,index.html,位置如下

3.粘贴代码,将下面代码粘贴到对应文件
ChatHandler

package com.example.chatdemo;import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.concurrent.CopyOnWriteArrayList;@Component
public class ChatHandler extends TextWebSocketHandler {private static final CopyOnWriteArrayList<WebSocketSession> sessions = new CopyOnWriteArrayList<>();private static final String LOG_FILE = "chat.log";// 新连接建立@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.add(session);System.out.println("新用户连接: " + session.getId());sendHistory(session);}// 处理消息@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {String msg = message.getPayload();System.out.println("收到消息: " + msg);// 广播消息(UTF-8编码保障)TextMessage encodedMsg = new TextMessage(msg.getBytes(StandardCharsets.UTF_8));broadcast(encodedMsg);// 持久化存储saveToFile(msg);}// 广播消息private void broadcast(TextMessage message) {sessions.forEach(s -> {try {if (s.isOpen()) {s.sendMessage(message);}} catch (IOException e) {System.err.println("消息发送失败: " + e.getMessage());}});}// 保存到文件(UTF-8编码)private void saveToFile(String message) {try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(LOG_FILE),StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.APPEND)) {writer.write(message);writer.newLine();} catch (IOException e) {System.err.println("文件保存失败: " + e.getMessage());}}// 发送历史记录private void sendHistory(WebSocketSession session) {try {if (Files.exists(Paths.get(LOG_FILE))) {Files.lines(Paths.get(LOG_FILE), StandardCharsets.UTF_8).forEach(line -> {try {session.sendMessage(new TextMessage(line));} catch (IOException e) {System.err.println("历史消息发送失败: " + e.getMessage());}});}} catch (IOException e) {System.err.println("历史记录加载失败: " + e.getMessage());}}
}

WebSocketConfig

package com.example.chatdemo;import com.example.chatdemo.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 {private final ChatHandler chatHandler;public WebSocketConfig(ChatHandler chatHandler) {this.chatHandler = chatHandler;}@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(chatHandler, "/chat").setAllowedOrigins("*");}
}

index.html

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>网络聊天室</title><style>#container {max-width: 600px;margin: 20px auto;padding: 20px;border: 1px solid #ddd;border-radius: 5px;}#messages {height: 300px;border: 1px solid #ccc;padding: 10px;margin-bottom: 10px;overflow-y: auto;}#status {color: #666;font-size: 0.9em;margin-bottom: 10px;}input[type="text"] {width: 70%;padding: 8px;margin-right: 5px;}button {padding: 8px 15px;background: #007bff;color: white;border: none;border-radius: 3px;cursor: pointer;}button:hover {background: #0056b3;}</style>
</head>
<body>
<div id="container"><div id="status">连接状态:等待连接...</div><div id="messages"></div><div><input type="text" id="msgInput" placeholder="输入消息..."><button onclick="sendMessage()">发送</button></div>
</div><script>let socket;const statusDiv = document.getElementById('status');const messagesDiv = document.getElementById('messages');// 初始化WebSocket连接function connect() {socket = new WebSocket('ws://' + window.location.host + '/chat');socket.onopen = () => {statusDiv.innerHTML = '连接状态:<span style="color:green">已连接</span>';console.log('WebSocket连接已建立');};socket.onmessage = (event) => {const msg = document.createElement('div');msg.textContent = event.data;messagesDiv.appendChild(msg);messagesDiv.scrollTop = messagesDiv.scrollHeight;};socket.onerror = (error) => {statusDiv.innerHTML = '连接状态:<span style="color:red">连接错误</span>';console.error('WebSocket错误:', error);};socket.onclose = () => {statusDiv.innerHTML = '连接状态:<span style="color:gray">已断开</span>';console.log('WebSocket连接已关闭');};}// 发送消息function sendMessage() {const input = document.getElementById('msgInput');if (input.value.trim()) {if (socket.readyState === WebSocket.OPEN) {socket.send(input.value);input.value = '';} else {alert('连接未就绪,请稍后重试!');}}}// 初始化连接connect();
</script>
</body>
</html>

3.本地运行

在浏览器输入网址,访问聊天室,出现下面的界面代表本地部署成功,代码成功

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20234114 2024-2025-2 《Python程序设计》实验一报告

20234114 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2341 姓名: 于家欢 学号:20234114 实验教师:王志强 实验日期:2025年3月21日 必修/选修: 公选课 1.实验内容熟悉Python开发环境;练习Python运行、调试技能;编写程序,练习变量和类型…

简易聊天室项目(环境搭建)

从零搭建简易聊天室项目 一.开发环境搭建 1.安装jdk23 访问 Oracle官网 或 OpenJDK镜像站下载,搜索安装教程安装配置 2.安装IDEA 访问 JetBrains官网下载社区版(免费)或旗舰,搜索安装教程安装配置 3.安装MAVEN 可参考b站视频安装 1)下载 访问Maven官网找到自己下载的压缩包…

L2 领导力

Hina...L2 领导力 需求层次 理论 人类受到各种需求的驱动。人是一种追求完全需求的动物。 管理设计对人力资源——我们的同事——的激活,来实现既定的目标,这是通过满足人类的各种需求来操纵人的行为做到的。 马斯洛的需求层次理论指出,一些需求比其他需求更基本,只有在基本…

Crypto类型总结(持续更新)

想做这样的一篇密码学总结的文章的想法主要来自于https://blog.csdn.net/weixin_45728976/article/details/109219997 这篇文章,对于这篇文章里面已经涉及到的内容的基础点不再进行繁琐的讲论。 接下来总结的主要是各种各样的crypto的魔改或者容易忘却的思路 1.unencode加密:…

树链剖分-重链剖分

树链剖分——重链剖分,我学的第一个蓝色算法树链剖分-重链剖分 前置知识 树形结构,链式前向星,线段树,DFS序,LCA 定义 树链剖分(树剖):将树分解为一条条不相交的,从祖先到孙子的链。 第零部分:建树与基本概念 建树:给定\(n\)个节点用链式前向星(或邻接表)建树 基本…

苍穹外卖-day05

redis基本入门 入门略过https://www.bilibili.com/video/BV1TP411v7v6?spm_id_from=333.788.videopod.episodes&vd_source=93f5f50fb9ce34ddae7abba08c6ea064&p=62 50-62级 记了感觉也不会看每次使用redis时需要先启动服务 在redis目录下,进入cmd窗口,输入以下命令启…

2025最新面试题-JVM面试题(二)

堆为什么进行分代设计老年代的担保机制 为什么Eden:S0:S1 是8:1:1 对象的创建以及分配过程方法区与元数据区以及持久代到底是什么关系? Full GC = young GC + Old GC + Meta Space GC 规范:方法区 实现: JDK1.7之前 永久代 持久代 Perm Space 类的总数 常量池大小 方法的…

YashanDB双引号

双引号是对标识符、密码定义和使用的扩展。使用双引号时,标识符、密码定义将支持特殊字符、数字,并且区分字母大小写。 双引号的使用位置(是否可出现在SELECT,FROM和WHERE后)和使用场景规则,以及双引号内字符串的长度限制,由双引号限定的标识符和密码本身决定,与是否加…

YashanDB故障状态

YashanDB检测到异常故障时,防止扩散影响,会将数据库的状态置为ABNORMAL,数据库处于故障只读状态,可以查询,不能执行写的业务。 当数据库为ABNORMAL状态时,可以查看V$DIAG_INCIDENT视图或告警日志明确故障原因。 --故障发生时,数据库状态为ABNORMAL SELECT STATUS FROM V…

YashanDB故障诊断架构

故障诊断架构由多个组件构成,包括自动诊断存储库、运行日志、告警日志等。其中运行日志、告警日志参考日志管理中说明。#自动诊断存储库自动诊断存储库是基于文件的存储库,用于存储数据库的诊断数据。它的目录结构如下(默认放在YASDB_DATA目录下,可设置参数进行配置):其中…

安利一个求职刷题小妙招、变身 offer 收割机 | 《趣玩》第 2 期

通义灵码目前支持的模型已经全面升级,包括 qwen 2.5、qwen 2.5-max,以及通过强化学习优化的增强版推理模型 qwq-plus。作者:王二 在AI技术狂飙突进的今天,程序员如何借力 AI 突破职业瓶颈?阿里云推出的通义灵码插件给出了答案!这款智能编码助手近期完成升级,支持多个业内…