基于SpringBoot+WebSocket實(shí)現(xiàn)網(wǎng)頁(yè)在線聊天室
從今天開(kāi)始帶你從零到一實(shí)現(xiàn)一套前后端分離、登錄攔截、實(shí)時(shí)消息推送的網(wǎng)頁(yè)聊天室系統(tǒng)。包含完整架構(gòu)、數(shù)據(jù)庫(kù)設(shè)計(jì)、登錄認(rèn)證、WebSocket 通信、全局異常處理
一、項(xiàng)目整體架構(gòu)概覽
項(xiàng)目采用經(jīng)典 Spring Boot 后端 + 原生前端 架構(gòu),輕量、易跑、邏輯清晰。
瀏覽器頁(yè)面 ├── login.html 登錄頁(yè) ├── register.html 注冊(cè)頁(yè) └── client.html 聊天主界面 ↓ HTTP / WebSocket Spring Boot 后端 ├── Controller 接口層(用戶/好友/消息/會(huì)話) ├── Interceptor 登錄攔截器 ├── Exception 全局異常處理 ├── WebSocket 實(shí)時(shí)消息推送 └── MyBatis 數(shù)據(jù)持久層 ↓ MySQL 用戶表、好友表、會(huì)話表、消息表、會(huì)話用戶關(guān)聯(lián)表
核心能力
- 登錄/注冊(cè) + Session 狀態(tài)保持
- 登錄攔截保護(hù)接口,未登錄無(wú)法訪問(wèn)
- 單聊/會(huì)話模式
- WebSocket 實(shí)時(shí)消息收發(fā)
- 在線用戶管理
- 全局統(tǒng)一返回與異常處理
二、前端頁(yè)面與交互設(shè)計(jì)
前端使用 原生 HTML + JS + jQuery,無(wú)框架、無(wú)打包、直接運(yùn)行。
1. 登錄頁(yè)面 login.html
- 用戶名/密碼輸入
- 表單 POST 提交到 /login 接口
- 登錄成功跳轉(zhuǎn)到 client.html
- 登錄失敗提示“請(qǐng)先登錄”
2. 聊天主界面 client.html
左側(cè):
- 個(gè)人信息展示
- 搜索框
- 會(huì)話列表 / 好友列表切換
- 會(huì)話/好友列表展示
右側(cè):
- 消息展示區(qū)(左右氣泡)
- 消息輸入框 + 發(fā)送按鈕
- WebSocket 實(shí)時(shí)收發(fā)消息
3. 前端狀態(tài)管理
- 登錄狀態(tài):HttpSession 維持
- 實(shí)時(shí)通信:
new WebSocket(ws://host/WebSocketMessage) - 頁(yè)面切換:通過(guò) class 控制 show/hide
- 消息列表:動(dòng)態(tài) DOM 拼接
三、后端技術(shù)棧
- Spring Boot 3.x
- Spring WebSocket
- MyBatis
- MySQL
- Tomcat 內(nèi)嵌容器
- 統(tǒng)一返回體 + 全局異常處理
四、核心功能實(shí)現(xiàn)詳解
1. 登錄認(rèn)證與 Session 機(jī)制
登錄接口邏輯:
@PostMapping("/login")
public Object login(String username, String password, HttpServletRequest req) {
User user = userMapper.selectByName(username);
if(user == null || !user.getPassword().equals(password)) {
return new User();
}
HttpSession session = req.getSession(true);
session.setAttribute("user", user);
return user;
}- 登錄成功把 User 存入 Session
- 后續(xù)請(qǐng)求通過(guò) Cookie 自動(dòng)攜帶 SessionID
2. 登錄攔截器(核心)
你之前寫的攔截器,保護(hù)需要登錄的接口:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("user") == null) {
response.setContentType("application/json;charset=utf-8");
response.setStatus(401);
response.getWriter().write("請(qǐng)先登錄");
return false;
}
return true;
}攔截路徑
- /friendList
- /message
- /sessionList
- /session
放行路徑
- /login
- /register
- /WebSocketMessage
- /**.html 靜態(tài)頁(yè)面
3. WebSocket 實(shí)時(shí)消息
核心流程:
- 用戶登錄成功
- 前端建立 WebSocket 連接
- 后端把用戶 ID → Session 存入 ConcurrentHashMap(線程安全)
- 發(fā)送消息時(shí),后端查詢會(huì)話內(nèi)所有用戶
- 逐個(gè)推送消息給在線用戶
- 消息落庫(kù)保存歷史記錄
// 在線用戶管理(線程安全)
private ConcurrentHashMap<Integer, WebSocketSession> sessions = new ConcurrentHashMap<>();
public void online(int userId, WebSocketSession session) {
sessions.put(userId, session);
}
public WebSocketSession getSession(int userId) {
return sessions.get(userId);
}4. 全局異常處理
專門處理:
- 404 找不到頁(yè)面(包括 favicon.ico)
- 用戶名重復(fù)
- 空指針
- 服務(wù)器內(nèi)部錯(cuò)誤
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NoResourceFoundException.class)
public Result handleNoResource() {
return Result.success(null);
}
@ExceptionHandler(Exception.class)
public Result handleError(Exception e) {
return Result.fail("服務(wù)器異常");
}
}作用:避免瀏覽器自動(dòng)請(qǐng)求 favicon.ico 觸發(fā)登錄攔截器瘋狂報(bào)錯(cuò)。
五、數(shù)據(jù)庫(kù)設(shè)計(jì)(5張表標(biāo)準(zhǔn)聊天結(jié)構(gòu))
- user 用戶表:userId, username, password
- friend 好友關(guān)系表:userId, friendId
- message_session 會(huì)話表:sessionId, lastTime
- message_session_user 會(huì)話-用戶關(guān)聯(lián)表
- message 消息表:messageId, fromId, sessionId, content, postTime
標(biāo)準(zhǔn)多對(duì)多、會(huì)話隔離、消息可追溯設(shè)計(jì)。
六、項(xiàng)目運(yùn)行與訪問(wèn)地址
啟動(dòng) Spring Boot 后直接訪問(wèn):
- 登錄:http://localhost:8080/login.html
- 注冊(cè):http://localhost:8080/register.html
- 聊天:http://localhost:8080/client.html
測(cè)試賬號(hào)
- zhangsan / 123
- lisi / 123
以上就是基于SpringBoot+WebSocket實(shí)現(xiàn)網(wǎng)頁(yè)在線聊天室的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot WebSocket網(wǎng)頁(yè)在線聊天室的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解
這篇文章主要介紹了SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解,要實(shí)現(xiàn)權(quán)限校驗(yàn),首先數(shù)據(jù)表和實(shí)體類上需要有權(quán)限字段,我的表中permission和gender是通過(guò)外鍵約束permission表和gender表實(shí)現(xiàn)枚舉的,因?yàn)榭赏卣剐愿?需要的朋友可以參考下2024-01-01
解決BeanUtils.copyProperties不支持復(fù)制集合的問(wèn)題
這篇文章主要介紹了解決BeanUtils.copyProperties不支持復(fù)制集合的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
JAVA實(shí)現(xiàn)異步調(diào)用實(shí)例代碼
在java平臺(tái),實(shí)現(xiàn)異步調(diào)用的角色主要三種角色:調(diào)用者、取貨憑證、真實(shí)數(shù)據(jù)。本篇文章給大家介紹java實(shí)現(xiàn)異步調(diào)用實(shí)例代碼,需要的朋友可以參考下2015-09-09
解決java.lang.IllegalStateException:Duplicate key異常問(wèn)題
java.lang.IllegalStateException:Duplicatekey異常在將List轉(zhuǎn)換為Map時(shí)出現(xiàn),解決方法是使用toMap()的重載方法,如果已經(jīng)存在則不再修改,直接使用上一個(gè)數(shù)據(jù)2025-03-03
Java Integer[]和int[]互相轉(zhuǎn)換方式
這篇文章主要介紹了Java Integer[]和int[]互相轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Java中的Opencv簡(jiǎn)介與開(kāi)發(fā)環(huán)境部署方法
OpenCV是一個(gè)開(kāi)源的計(jì)算機(jī)視覺(jué)和圖像處理庫(kù),提供了豐富的圖像處理算法和工具,它支持多種圖像處理和計(jì)算機(jī)視覺(jué)算法,可以用于物體識(shí)別與跟蹤、圖像分割與邊緣檢測(cè)、圖像特征提取與描述等應(yīng)用,本文介紹Java中的Opencv簡(jiǎn)介與開(kāi)發(fā)環(huán)境部署方法,感興趣的朋友一起看看吧2025-01-01

