
简介本资源为基于SpringBoot的在线聊天系统毕业设计完整源码包面向计算机、人工智能、通信工程等专业正在做课程设计、期末大作业或毕设的学生也适合作为项目初期立项演示与进阶学习参考。项目采用SpringBootNettyMUIH5PlusNginxFastDFS分布式文件系统搭建前端聊天系统涵盖登录注册、互信、通讯录、发现、我等模块并加入扫一扫、朋友圈等功能后台管理系统侧重实时聊天能力工程按前端接口、数据层、Netty聊天接口及网络编程示例等模块拆分结构清晰便于二次开发。压缩包共290个文件以java源码、class字节码、xml配置、html页面、css与js脚本、properties配置及图片音频资源为主整体约1.35MB。目前已有148人学习下载可帮助读者快速理解分布式聊天系统的分层设计与核心实现并在此基础上修改扩展出新的功能。1. 基于 Spring Boot 的在线聊天系统从源码结构到能跑起来的那条最短路径毕业设计选题里基于 Spring Boot 的在线聊天系统几乎是每年都有人做的常青款。原因很直接它同时踩中了 WebSocket 实时通信、用户会话管理、消息持久化三个能写进论文的技术点又不像电商秒杀那样对性能压榨到极致。但真正动手时多数人卡住的地方不是聊天本身而是拿到一份源码后不知道从哪读起——配置类、拦截器、消息编解码、前端连接地址散落在十几个文件里改一个端口能连带三处报错。这篇笔记按一线落地的顺序拆先讲清这套系统由哪些模块咬合而成再给出本地跑通的最小步骤和必调参数最后把毕业设计答辩时最容易被追问的几个坑提前填上。适合正在做 Java 方向毕业设计、需要一份能讲明白也能改得动的聊天系统源码的同学。2. 在线聊天系统的模块拆解谁在维持那条长连接2.1 从 HTTP 到 WebSocket 的握手链路普通 Spring Boot 项目是请求-响应模型浏览器发一次请求服务端返回一次就断开。聊天系统不行服务端得主动推消息给客户端所以核心是 WebSocket 这条全双工通道。在 Spring Boot 里通常用spring-boot-starter-websocket起步配置一个WebSocketConfig实现WebSocketConfigurer把自定义的Handler注册到某个路径上比如/chat。握手阶段浏览器会带Upgrade: websocket头Spring 内部用HandshakeInterceptor拦截这次握手你可以在beforeHandshake里从 session 或 token 中取出用户身份塞进 attributes这样后续每条消息都知道是谁发的。这里有个容易忽略的点WebSocket 握手走的还是 HTTP所以你的登录拦截器、跨域配置对它同样生效。很多人前端连不上报 403第一反应是 WebSocket 配置错了其实是 Spring Security 或自定义拦截器把握手请求拦了。常见做法是在拦截器里放行/chat/**这类路径或者把鉴权逻辑挪到HandshakeInterceptor里做。2.2 消息模型与持久化的表结构设计聊天消息要不要落库取决于你的论文想写到什么深度。只做在线转发内存里一个ConcurrentHashMap用户ID, WebSocketSession就够了但要支持离线消息、历史记录查询就得建表。我一般会设计三张核心表用户表存账号密码昵称会话表记录谁和谁建立了会话单聊就是两个用户 ID群聊则关联群组消息表存每条消息的内容、发送者、接收者、时间戳和已读状态。消息表的主键用自增还是雪花 ID 要看场景。单机部署自增够用但如果论文里提到分布式或者多节点自增会在合并时冲突这时候用雪花算法生成有序 ID 更稳妥。字段类型上消息内容用TEXT而不是VARCHAR(255)因为聊天里发一段长文本很常见255 会截断。时间戳统一用DATETIME并让应用层写入不要依赖数据库的CURRENT_TIMESTAMP否则多实例部署时区不一致会出玄学问题。2.3 在线状态与心跳保活机制WebSocket 连接不是建立后就永远活着。网络抖动、代理超时、浏览器休眠都会让连接悄悄断掉而服务端可能过很久才感知到。所以需要心跳客户端每隔一段时间发一个 ping 帧或自定义的{type:ping}消息服务端收到后回 pong同时刷新该会话的最后活跃时间。服务端再起一个定时任务扫描超过阈值没收到心跳的会话主动关闭并清理在线列表。在线状态的存储也有讲究。单机可以用ConcurrentHashMap但要注意并发读写时用putIfAbsent而不是先get再put否则同一用户重复登录会覆盖掉旧 session 导致旧连接泄漏。如果论文涉及多节点在线状态得放到 Redis 里用SET结构存用户 ID配合过期时间做自动清理。这一步是很多毕业设计从能跑到能答辩的分水岭因为老师很爱问用户断线了你怎么知道。3. 本地跑通的最小步骤从导入到发出第一条消息3.1 环境准备与依赖版本选择拿到源码压缩包后先别急着点运行。第一步是确认 JDK 版本和 Spring Boot 版本匹配。Spring Boot 3.x 要求 JDK 17 起步如果你本机是 JDK 8导入后一堆类找不到。热搜里常出现springboot版本太高的抱怨多半就是这个原因。稳妥做法是看pom.xml里parent的版本号2.7.x 配 JDK 8 或 113.x 配 JDK 17。数据库一般用 MySQL 5.7 或 8.08.0 的驱动类名是com.mysql.cj.jdbc.Driver5.7 是com.mysql.jdbc.Driver写错会报驱动加载失败。!-- pom.xml 关键依赖版本按你实际源码调整 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-websocket/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency上面三个依赖分别负责 WebSocket 通信、Web 层和数据库连接。注意mysql-connector-java在 Spring Boot 3.x 里已经改名为mysql-connector-j如果版本对不上启动时会报ClassNotFoundException。参数上scope设为runtime表示编译时不需要运行时才加载这是官方推荐写法。3.2 数据库初始化与配置文件修改源码里通常会带一个.sql文件先在 MySQL 里建库再执行它。建库时字符集用utf8mb4不要用utf8因为utf8在 MySQL 里是三个字节存不了 emoji聊天系统里用户发个表情就报错。执行完 SQL 后改application.yml或application.properties里的连接信息。spring: datasource: url: jdbc:mysql://localhost:3306/chat_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver server: port: 8080serverTimezone必须显式指定否则 MySQL 8.0 会报时区错误。characterEncoding写utf8mb4而不是utf8和建库时保持一致。端口如果被占用改server.port即可但改完记得同步改前端里 WebSocket 的连接地址否则前端还连旧端口。3.3 启动项目与前端连接验证后端启动看到Tomcat started on port(s): 8080就算起来了。前端如果是 Vue 打包后放进 Spring Boot 的static目录直接访问http://localhost:8080即可如果是独立开发服务器注意跨域配置。WebSocket 的连接地址写法是ws://localhost:8080/chat不是http://。前端用原生WebSocket对象或SockJS都行原生更轻量。// 前端建立连接并发送第一条消息 const socket new WebSocket(ws://localhost:8080/chat); socket.onopen () { // 连接建立后发送一条测试消息 socket.send(JSON.stringify({ type: chat, to: user2, content: hello })); }; socket.onmessage (event) { // 收到服务端推送的消息 console.log(收到:, event.data); }; socket.onerror (err) { console.error(连接出错, err); };onopen里发消息是安全的因为此时握手已完成。如果放在new WebSocket之后立刻send会报InvalidStateError因为连接还没就绪。onmessage里拿到的event.data是字符串如果后端发的是 JSON 字符串前端要JSON.parse一次。验证是否跑通开两个浏览器窗口分别登录不同账号互发消息能实时收到就算成功。4. 消息可靠性与并发处理别让消息丢了或串了4.1 消息发送失败的重试与确认机制WebSocket 的send方法本身不保证送达。如果连接刚好在发送瞬间断开消息就丢了而且不会抛异常。要做得靠谱一点得在应用层加确认客户端发消息时带一个本地生成的msgId服务端收到后回一个ack帧带上同样的msgId客户端收到ack才把消息标记为已发送超时没收到就重发。这个机制在论文里可以写成基于消息 ID 的可靠投递是个加分项。服务端这边如果接收方不在线消息要落库并标记为未读等对方上线后拉取。这里有个顺序问题先落库再推送还是先推送再落库我一般先落库因为落库失败可以立刻告诉发送方而推送失败不影响数据完整性。推送失败时把消息留在未读表里下次上线补推。4.2 多用户并发下的 Session 管理WebSocketSession不是线程安全的多个线程同时往同一个 session 写数据会报IllegalStateException: TEXT_PARTIAL_WRITING。解决办法是给每个 session 包一层ConcurrentWebSocketSessionDecorator或者自己加锁。Spring 提供了ConcurrentWebSocketSessionDecorator构造时传 session、发送超时时间和缓冲区大小内部用队列串行化写操作。// 包装 session 保证并发安全 WebSocketSession safeSession new ConcurrentWebSocketSessionDecorator( rawSession, 5000, 512 * 1024);第一个参数是原始 session第二个是发送超时毫秒数超过这个时间还没发完就关闭连接第三个是缓冲区字节数超过会限制发送。缓冲区别设太小否则大消息会被截断也别太大否则内存涨得快。512KB 对文本聊天够用。4.3 群聊消息的扇出与顺序保证群聊的本质是一条消息要发给群里所有人。简单做法是遍历群成员列表逐个send但成员多的时候这是 O(n) 次网络写而且如果中途某个 session 卡住后面的人就延迟收到。更好的做法是把消息投递到每个成员各自的发送队列由队列的消费者异步发送这样互不阻塞。顺序上同一个群的消息要保证大家看到的顺序一致可以在服务端给每条群消息分配一个递增的序号客户端按序号排序后再展示。5. 避坑与排查那些让聊天系统看起来能跑的陷阱5.1 连接建立成功但收不到消息现象是前端onopen触发了但onmessage一直不响应。原因通常是服务端把消息发到了错误的 session 上或者 session 的isOpen()已经是 false 但没被清理。排查时先在服务端send前打印session.getId()和isOpen()确认目标 session 状态。解决方式是在发送前判断isOpen()false 就从在线列表移除并落库为离线消息。5.2 中文消息乱码现象是收到的消息里中文变成问号或方块。原因一般是数据库字符集不是utf8mb4或者 WebSocket 传输时没指定编码。排查时先看数据库表的字符集SHOW CREATE TABLE message能直接看到。解决方式是把库、表、连接三处的字符集统一成utf8mb4WebSocket 的TextMessage默认就是 UTF-8一般不用额外设置。5.3 页面刷新后历史消息丢失现象是刷新浏览器后聊天记录清空。原因是消息只存在前端内存里没从后端拉取。解决方式是在页面加载时调一个历史消息接口按会话 ID 和时间倒序分页查询。注意分页要按时间倒序再反转否则展示顺序会乱。接口里加个lastMsgId参数做游标分页比offset分页在消息量大时更高效。5.4 多标签页登录同一账号互相顶掉现象是同一个账号开两个标签页一个发消息另一个收不到。原因是后登录的 session 覆盖了在线列表里的旧 session。解决方式看产品需求要么允许同一账号多端在线在线列表里存一个 session 集合要么只允许单端新登录时给旧连接发一个下线通知再关闭。毕业设计里推荐做单端逻辑简单且好演示。5.5 打包后 WebSocket 连不上现象是开发环境正常打成 jar 部署后前端连不上。原因通常是前端里 WebSocket 地址写死了localhost部署后应该用当前页面的 host。解决方式是用window.location.host动态拼接或者用相对路径让反向代理处理。如果用了 Nginx还要在配置里加Upgrade和Connection头转发否则握手会被 Nginx 拦下。6. 从能跑到能答辩压测、扩展与一个可复用的调试习惯把系统跑起来只是起点答辩时老师更关心你怎么证明它扛得住。压测不用上专业工具写个简单的 Java 客户端起几百个线程连上去发消息观察服务端内存和响应延迟就够了。重点看两个指标连接数上去后消息延迟是否线性增长以及断开重连后消息是否补推成功。前者反映你的 session 管理有没有瓶颈后者反映可靠性设计是否闭环。扩展方向上如果论文想往深了写可以把在线状态和未读消息挪到 Redis用Pub/Sub做跨节点消息广播这样多实例部署时用户连到哪台机器都能收到消息。再进一步消息表按时间分表历史查询走冷数据热数据只留最近几天。这些不用全做挑一个在论文里讲清楚选型理由和验证数据就够。最后说个我自己的习惯每次改完配置或代码先开两个浏览器窗口互发三条消息——一条纯文本、一条带 emoji、一条长文本。这三条能覆盖编码、截断、并发三个最容易翻车的点。跑通了再往下做功能比写完一堆代码再回头查错省时间得多。这套系统本身不复杂难的是把每个环节的边界条件想清楚希望帮到你。本文还有配套的精品资源点击获取