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 開啟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;
/**
* 開啟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());
}
/**
* 斷開連接
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
if (webSocketMap.containsKey(userId)) {
webSocketMap.remove(userId);
subOnlineCount();
}
// log.info("【websocket消息】連接斷開, 總數(shù):{}", webSocketSet.size());
log.info("[連接ID:{}] 斷開連接, 當(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)文章
使用ServletUtil.write方法下載接口文件中文亂碼問(wèn)題解決
本文主要介紹了使用ServletUtil.write方法下載接口文件中文亂碼問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
java中PriorityBlockingQueue的入隊(duì)知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理一篇關(guān)于java中PriorityBlockingQueue的入隊(duì)知識(shí)點(diǎn)總結(jié)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2021-01-01
java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb實(shí)現(xiàn)示例
這篇文章主要為大家介紹了java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Spring AOP實(shí)現(xiàn)功能權(quán)限校驗(yàn)功能的示例代碼
本篇文章主要介紹了Spring AOP實(shí)現(xiàn)功能權(quán)限校驗(yàn)功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Spring Boot 的創(chuàng)建和運(yùn)行示例代碼詳解
Spring Boot 的誕生是為了簡(jiǎn)化Spring程序的開發(fā),今天給大家介紹下Spring Boot 的創(chuàng)建和運(yùn)行,主要包括Spring Boot基本概念和springboot優(yōu)點(diǎn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-07-07
Java開發(fā)環(huán)境jdk 1.8安裝配置方法(Win7 64位系統(tǒng)/windows server 2008)
這篇文章主要介紹了Java開發(fā)環(huán)境配置方法(Win7 64位系統(tǒng)/windows server 2008),需要的朋友可以參考下2016-10-10

