Java實現(xiàn)使用Websocket發(fā)送消息詳細(xì)代碼舉例
前言
- 需求背景:之前做了個樓棟房間數(shù)量出租了多少,需要在數(shù)據(jù)大屏上實時展示
- 解決方案:以切面攔截出租接口,當(dāng)有房間出租時重新查詢相關(guān)數(shù)據(jù),封裝好用websocket實時傳送前端展示
一、websocket 簡介
WebSocket 是一種在單個TCP連接上進行全雙工通信的協(xié)議。WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)。在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸。
二、websocket 如何使用
1.引入依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.創(chuàng)建 WebSocketConfig
package com.alpari.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author wangrui
* @date 2023/11/8
**/
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpoint() {
return new ServerEndpointExporter();
}
/**
* 注意事項:
* WebSocket啟動的時候優(yōu)先于spring容器,從而導(dǎo)致在WebSocketServer中調(diào)用業(yè)務(wù)Service會報空指針異常
* 所以需要在WebSocketServer中將所需要用到的service給靜態(tài)初始化一下
* 此處提前注入
*/
// @Autowired
// private void setXxx(XxxService xxxService) {
// WebSocketServer.xxxService = xxxService;
// }
}3.創(chuàng)建 WebSocketServer
package com.alpari.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author wangrui
* @date 2023/11/8
* @description: 若在此類中直接調(diào)用service方法失敗,需要加上:public static XxxService xxxService; 另外在config中注入實例
**/
@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{userId}")
public class WebSocketServer {
/**
* 當(dāng)前連接數(shù)
*/
private static int onlineCount = 0;
/**
* concurrent包的線程安全Set,用來存放每個客戶端對應(yīng)的MyWebSocket對象
*/
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
/**
* 與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
*/
private Session session;
/**
* 接收的用戶id
*/
private String userId;
/**
* 連接建立成功調(diào)用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
webSocketSet.add(this);
addOnlineCount(); //在線數(shù)加1
log.info("有新連接加入!當(dāng)前在線人數(shù)為" + getOnlineCount());
this.userId = userId;
try {
sendMessage("連接成功");
} catch (IOException e) {
log.error("websocket IO異常", e);
}
}
/**
* 連接關(guān)閉調(diào)用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
subOnlineCount(); //在線數(shù)減1
log.info("有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + getOnlineCount());
}
/**
* 收到客戶端消息后調(diào)用的方法
*
* @param message 客戶端發(fā)送過來的消息
*/
@OnMessage
public void onMessage(String message) {
log.info("來自客戶端的消息:" + message);
//群發(fā)消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
log.error("發(fā)送消息失敗", e);
}
}
}
/**
* @param error 錯誤
*/
@OnError
public void onError( Throwable error) {
log.error("發(fā)生錯誤", error);
}
/**
* 發(fā)送消息
* @param message 消息
* @throws IOException 異常
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群發(fā)自定義消息
*/
public static void sendInfo(String message, @PathParam("userId") String userId) {
log.info("消息內(nèi)容:" + message);
for (WebSocketServer item : webSocketSet) {
try {
//這里可以設(shè)定只推送給這個sid的,為null則全部推送
if (userId == null) {
item.sendMessage(message);
} else if (item.userId.equals(userId)) {
item.sendMessage(message);
}
} catch (IOException e) {
log.error("消息發(fā)送失敗", e);
}
}
}
/**
* 獲取在線人數(shù)
* @return 在線人數(shù)
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 在線人數(shù)加一
*/
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
/**
* 在線人數(shù)減一
*/
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
4.在線測試
在線ws測試地址:http://www.jsons.cn/websocket/
- 輸入測試

- 后端返回的結(jié)果

5.模擬消息發(fā)送
/**
* 切面攔截數(shù)據(jù)模擬給指定用戶或全部用戶發(fā)消息
*/
public void sendMessage(String userid) {
// 此處模擬數(shù)據(jù)大屏推送,以切面方式攔截相關(guān)接口,若數(shù)據(jù)發(fā)生變化,則將數(shù)據(jù)推送,不傳id則全部發(fā)送
String msg = "模擬數(shù)據(jù)";
WebSocketServer.sendInfo(msg, userid);
log.info("發(fā)送消息成功,消息內(nèi)容:{},接收人:{}", msg, userid);
}
總結(jié)
到此這篇關(guān)于Java實現(xiàn)使用Websocket發(fā)送消息的文章就介紹到這了,更多相關(guān)Java Websocket發(fā)送消息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中使用WebSocket的幾種方式
- 如何在Java中使用WebSocket協(xié)議
- springboot整合websocket后啟動報錯(javax.websocket.server.ServerContainer not available)
- Java WebSocket客戶端接收大量數(shù)據(jù)的三種方案
- 使用Java WebSocket獲取客戶端IP地址的示例代碼
- Java中實現(xiàn)WebSocket方法詳解
- 教你如何使用Java實現(xiàn)WebSocket
- 一步步教你如何使用Java實現(xiàn)WebSocket
- java后端+前端使用WebSocket實現(xiàn)消息推送的詳細(xì)流程
- JAVA 日常開發(fā)中Websocket示例詳解
相關(guān)文章
Java如何使用Jetty實現(xiàn)嵌入式的Servlet容器
這篇文章主要介紹了Java使用Jetty實現(xiàn)嵌入式的Servlet容器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,下面我們來一起了解一下吧2019-06-06
使用Springboot+Vue實現(xiàn)文件上傳和下載功能
本文介紹了如何使用Springboot結(jié)合Vue進行圖書信息管理系統(tǒng)開發(fā),包括數(shù)據(jù)庫表的創(chuàng)建,實體類、Dao層、Service層和Controller層的編寫,重點講解了文件上傳和下載功能的實現(xiàn),感興趣的朋友跟隨小編一起看看吧2024-09-09
Java超詳細(xì)教你寫一個銀行存款系統(tǒng)案例
這篇文章主要介紹了怎么用Java來寫一個銀行的存款系統(tǒng),銀行存款主要有賬號和存款金額兩個屬性,感興趣的朋友跟隨文章往下看看吧2022-03-03
springboot+thymeleaf+druid+mybatis 多模塊實現(xiàn)用戶登錄功能
這篇文章主要介紹了springboot+thymeleaf+druid+mybatis 多模塊實現(xiàn)用戶登錄功能,本文通過示例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07

