很多時候,我們在項目中都有用到websocket的場景,如數(shù)據(jù)實時更新、實時聊天,實時通知等,下面我將帶大家了解什么是websocket,websocket和http的區(qū)別。websocket是什么?和http的區(qū)別? WebSocket 是一種在單個 TCP 連接上實現(xiàn)全雙工通信的網(wǎng)絡(luò)協(xié)議,它允許客戶端和服務(wù)器之間建立持久連接,實現(xiàn)實時雙向數(shù)據(jù)傳輸。與傳統(tǒng)的 HTTP 協(xié)議(請求 - 響應(yīng)模式)相比,WebSocket 最大的優(yōu)勢是服務(wù)器可以主動向客戶端推送數(shù)據(jù),無需客戶端頻繁輪詢,極大提升了實時性和效率。WebSocket 的核心作用
實時雙向通信
打破 HTTP “客戶端請求→服務(wù)器響應(yīng)” 的單向模式,實現(xiàn)服務(wù)器和客戶端的 “平等對話”:
例:聊天應(yīng)用中,A 發(fā)送消息后,服務(wù)器可立即將消息推送給 B,無需 B 反復(fù)刷新頁面。
減少網(wǎng)絡(luò)開銷
低延遲響應(yīng)
避免了 HTTP 輪詢(客戶端定時發(fā)送請求)帶來的延遲和資源浪費:
與 HTTP 的對比
| | |
---|
| 單向(客戶端請求→服務(wù)器響應(yīng)) | |
| | |
| | |
| | |
自己實現(xiàn)websocket服務(wù)需要基于TCP協(xié)議處理握手、幀解析和雙向通信。
(1)握手階段
(2)幀解析與構(gòu)建
(3)廣播功能
注解式的實現(xiàn)是我們常用的websocket實現(xiàn),只需要使用@ServerEndpoint注解標(biāo)記類為websocket的服務(wù)端點,客戶端就可以使用ws://地址:端口/端點進行連接。下面是簡單的實現(xiàn)
@ServerEndpoint("/chat")
public class ChatServer {
private static final Set<Session> onlineSessions =
Collections.synchronizedSet(new HashSet<>());
* 客戶端連接建立時觸發(fā)(對應(yīng)@OnOpen)
*/
@OnOpen
public void onOpen(Session session) {
onlineSessions.add(session);
System.out.println("新客戶端連接,會話ID:" + session.getId());
broadcast("系統(tǒng)消息:有新用戶加入,當(dāng)前在線:" + onlineSessions.size() + "人");
}
* 客戶端斷開連接時觸發(fā)(對應(yīng)@OnClose)
*/
@OnClose
public void onClose(Session session) {
onlineSessions.remove(session);
System.out.println("客戶端斷開,會話ID:" + session.getId());
broadcast("系統(tǒng)消息:有用戶離開,當(dāng)前在線:" + onlineSessions.size() + "人");
}
* 收到客戶端消息時觸發(fā)(對應(yīng)@OnMessage)
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到消息(" + session.getId() + "):" + message);
broadcast("用戶" + session.getId().substring(0, 6) + ":" + message);
}
* 發(fā)生錯誤時觸發(fā)(對應(yīng)@OnError)
*/
@OnError
public void onError(Session session, Throwable error) {
System.err.println("會話錯誤(" + session.getId() + "):" + error.getMessage());
}
* 廣播消息給所有在線客戶端
*/
private static void broadcast(String message) {
for (Session session : onlineSessions) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
System.err.println("廣播失?。? + e.getMessage());
}
}
}
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
spring websocket實現(xiàn)-SimpMessagingTemplate
spring 是spring對JSR 356之上的更高封裝,簡化消息發(fā)送,整合spring生態(tài),SimpMessagingTemplate 消息發(fā)送更為簡便。
SimpMessagingTemplate
會話方式
messagingTemplate.convertAndSend("/topic/news", "新聞內(nèi)容");
messagingTemplate.convertAndSendToUser("user123", "/queue/msg", "私信");
廢話不多說,項目代碼看一下。簡單三步實現(xiàn)。
1.pom引入spring-boot-starter-websocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.注入SimpMessagingTemplate
private final SimpMessagingTemplate websocketTemplate;
3.發(fā)送消息
websocketTemplate.convertAndSend("/topic/device-updates", message);
這種方式有一個問題:一直發(fā)送(如前端訂閱頁面關(guān)閉),我需要只有訂閱者在線的時候才發(fā)送。于是根據(jù)spring websocket 做了一個監(jiān)聽
然后再發(fā)送消息時,對在線數(shù)進行檢查
這是后端所需要實現(xiàn)的,前端我們只需要進行訂閱就可以了。
前端我們引入兩個js
<script src="/static/util/sockjs.min.js"></script>
<script src="/static/util/stomp.min.js"></script>
然后訂閱后端的destination
該文章在 2025/8/29 12:23:03 編輯過