SpringBoot實(shí)現(xiàn)WebSocket即時(shí)通訊的示例代碼
1、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.3</version> </dependency>
2、WebSocketConfig 開(kāi)啟WebSocket
package com.shucha.deveiface.web.config; /** * @author tqf * @Description * @Version 1.0 * @since 2022-04-12 15:35 */ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * 開(kāi)啟WebSocket */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
3、WebSocketServer
package com.shucha.deveiface.web.ws; /** * @author tqf * @Description * @Version 1.0 * @since 2022-04-12 15:33 */ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; @Component @ServerEndpoint("/webSocket/{userId}") @Slf4j public class WebSocketServer { private Session session; private String userId; /**靜態(tài)變量,用來(lái)記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。*/ private static int onlineCount = 0; private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>(); /** * concurrent包的線程安全set,用來(lái)存放每個(gè)客戶端對(duì)應(yīng)的MyWebSocket對(duì)象 */ private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap(); /** * 為了保存在線用戶信息,在方法中新建一個(gè)list存儲(chǔ)一下【實(shí)際項(xiàng)目依據(jù)復(fù)雜度,可以存儲(chǔ)到數(shù)據(jù)庫(kù)或者緩存】 */ private final static List<Session> SESSIONS = Collections.synchronizedList(new ArrayList<>()); /** * 建立連接 * @param session * @param userId */ @OnOpen public void onOpen(Session session, @PathParam("userId") String userId) { this.session = session; this.userId = userId; webSocketSet.add(this); SESSIONS.add(session); if (webSocketMap.containsKey(userId)) { webSocketMap.remove(userId); webSocketMap.put(userId,this); } else { webSocketMap.put(userId,this); addOnlineCount(); } // log.info("【websocket消息】有新的連接, 總數(shù):{}", webSocketSet.size()); log.info("[連接ID:{}] 建立連接, 當(dāng)前連接數(shù):{}", this.userId, webSocketMap.size()); } /** * 斷開(kāi)連接 */ @OnClose public void onClose() { webSocketSet.remove(this); if (webSocketMap.containsKey(userId)) { webSocketMap.remove(userId); subOnlineCount(); } // log.info("【websocket消息】連接斷開(kāi), 總數(shù):{}", webSocketSet.size()); log.info("[連接ID:{}] 斷開(kāi)連接, 當(dāng)前連接數(shù):{}", userId, webSocketMap.size()); } /** * 發(fā)送錯(cuò)誤 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.info("[連接ID:{}] 錯(cuò)誤原因:{}", this.userId, error.getMessage()); error.printStackTrace(); } /** * 收到消息 * @param message */ @OnMessage public void onMessage(String message) { // log.info("【websocket消息】收到客戶端發(fā)來(lái)的消息:{}", message); log.info("[連接ID:{}] 收到消息:{}", this.userId, message); } /** * 發(fā)送消息 * @param message * @param userId */ public void sendMessage(String message,Long userId) { WebSocketServer webSocketServer = webSocketMap.get(String.valueOf(userId)); if (webSocketServer!=null){ log.info("【websocket消息】推送消息, message={}", message); try { webSocketServer.session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); log.error("[連接ID:{}] 發(fā)送消息失敗, 消息:{}", this.userId, message, e); } } } /** * 群發(fā)消息 * @param message */ public void sendMassMessage(String message) { try { for (Session session : SESSIONS) { if (session.isOpen()) { session.getBasicRemote().sendText(message); log.info("[連接ID:{}] 發(fā)送消息:{}",session.getRequestParameterMap().get("userId"),message); } } } catch (Exception e) { e.printStackTrace(); } } /** * 獲取當(dāng)前連接數(shù) * @return */ public static synchronized int getOnlineCount() { return onlineCount; } /** * 當(dāng)前連接數(shù)加一 */ public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } /** * 當(dāng)前連接數(shù)減一 */ public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } }
4、測(cè)試連接發(fā)送和接收消息
package com.shucha.deveiface.web.controller; import com.alibaba.fastjson.JSONObject; import com.shucha.deveiface.web.ws.WebSocketServer; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author tqf * @Description * @Version 1.0 * @since 2022-04-12 15:44 */ @RestController @RequestMapping("/web") public class TestWebSocket { @Autowired private WebSocketServer webSocketServer; /** * 消息發(fā)送測(cè)試 */ @GetMapping("/test") public void test(){ for (int i=1;i<4;i++) { WebsocketResponse response = new WebsocketResponse(); response.setUserId(String.valueOf(i)); response.setUserName("姓名"+ i); response.setAge(i); webSocketServer.sendMessage(JSONObject.toJSONString(response), Long.valueOf(String.valueOf(i))); } } /** * 群發(fā)消息測(cè)試(給當(dāng)前連接用戶發(fā)送) */ @GetMapping("/sendMassMessage") public void sendMassMessage(){ WebsocketResponse response = new WebsocketResponse(); response.setUserName("群發(fā)消息模板測(cè)試"); webSocketServer.sendMassMessage(JSONObject.toJSONString(response)); } @Data @Accessors(chain = true) public static class WebsocketResponse { private String userId; private String userName; private int age; } }
5、在線測(cè)試地址
6、測(cè)試截圖
訪問(wèn)測(cè)試發(fā)送消息:http://localhost:50041//web/test
測(cè)試訪問(wèn)地址:ws://192.168.0.115:50041/webSocket/1 wss://192.168.0.115:50041/webSocket/2
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)WebSocket即時(shí)通訊的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot WebSocket即時(shí)通訊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+WebSocket實(shí)現(xiàn)消息推送功能
- springboot結(jié)合websocket聊天室實(shí)現(xiàn)私聊+群聊
- SpringBoot整合WebSocket的客戶端和服務(wù)端的實(shí)現(xiàn)代碼
- SpringBoot+WebSocket實(shí)現(xiàn)即時(shí)通訊的方法詳解
- SpringBoot整合websocket實(shí)現(xiàn)即時(shí)通信聊天
- SpringBoot使用WebSocket實(shí)現(xiàn)前后端交互的操作方法
- SpringBoot+WebSocket實(shí)現(xiàn)多人在線聊天案例實(shí)例
- SpringBoot整合WebSocket實(shí)現(xiàn)聊天室流程全解
相關(guān)文章
Java亂碼問(wèn)題解決方法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
開(kāi)發(fā)java應(yīng)用出現(xiàn)亂碼是很常見(jiàn)的,畢竟現(xiàn)在unicode的使用還不是很廣泛,下面給大家分享Java亂碼問(wèn)題解決方法,感興趣的朋友一起看看吧2017-07-07JAVA匿名內(nèi)部類語(yǔ)法分析及實(shí)例詳解
這篇文章主要介紹了JAVA匿名內(nèi)部類語(yǔ)法分析及實(shí)例詳解,匿名內(nèi)部類可以使你的代碼更加簡(jiǎn)潔,它與局部類很相似,不同的是它沒(méi)有類名,如果某個(gè)局部類你只需要用一次,那么你就可以使用匿名內(nèi)部類。對(duì)此感興趣的可以了解一下2020-07-07如何修改json字符串中某個(gè)key對(duì)應(yīng)的value值
這篇文章主要介紹了如何修改json字符串中某個(gè)key對(duì)應(yīng)的value值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11從零開(kāi)始讓你的Spring?Boot項(xiàng)目跑在Linux服務(wù)器
這篇文章主要給大家介紹了如何從零開(kāi)始讓你的Spring?Boot項(xiàng)目跑在Linux服務(wù)器的相關(guān)資料,由于springboot是內(nèi)嵌了tomcat,所以可以直接將項(xiàng)目打包上傳至服務(wù)器上,需要的朋友可以參考下2021-11-11基于Java實(shí)現(xiàn)Avro文件讀寫(xiě)功能
大家好,本篇文章主要講的是基于Java實(shí)現(xiàn)Avro文件讀寫(xiě)功能,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02手把手教你從零設(shè)計(jì)一個(gè)java日志框架
Java里的各種日志框架,相信大家都不陌生。Log4j/Log4j2/Logback/jboss logging等等,其實(shí)這些日志框架核心結(jié)構(gòu)沒(méi)什么區(qū)別,只是細(xì)節(jié)實(shí)現(xiàn)上和其性能上有所不同。本文帶你從零開(kāi)始,一步一步的設(shè)計(jì)一個(gè)日志框架2021-02-02Java?中的?Lambda?List?轉(zhuǎn)?Map?的多種方法詳解
這篇文章主要介紹了Java中的Lambda?List轉(zhuǎn)Map幾種方式,傳統(tǒng)的方式又顯得太臃腫,于是就想到 Lambda 神器,今天我們就來(lái)看看都有哪幾種轉(zhuǎn)換方式(List -> Map),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-07-07idea打開(kāi)和讀取*properties文件亂碼的解決
本文主要介紹了idea打開(kāi)和讀取*properties文件亂碼的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09