溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot怎么實現(xiàn)WebSocket即時通訊

發(fā)布時間:2022-04-14 10:31:57 來源:億速云 閱讀:247 作者:iii 欄目:開發(fā)技術(shù)

這篇“SpringBoot怎么實現(xiàn)WebSocket即時通訊”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“SpringBoot怎么實現(xiàn)WebSocket即時通訊”文章吧。

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)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計成線程安全的。*/
    private static int onlineCount = 0;
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
 
    /**
     * concurrent包的線程安全set,用來存放每個客戶端對應(yīng)的MyWebSocket對象
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap();
 
    /**
     * 為了保存在線用戶信息,在方法中新建一個list存儲一下【實際項目依據(jù)復(fù)雜度,可以存儲到數(shù)據(jù)庫或者緩存】
     */
    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ā)送錯誤
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.info("[連接ID:{}] 錯誤原因:{}", this.userId, error.getMessage());
        error.printStackTrace();
    }
 
    /**
     * 收到消息
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        // log.info("【websocket消息】收到客戶端發(fā)來的消息:{}", 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、測試連接發(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ā)送測試
     */
    @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ā)消息測試(給當(dāng)前連接用戶發(fā)送)
     */
    @GetMapping("/sendMassMessage")
    public void sendMassMessage(){
        WebsocketResponse response = new WebsocketResponse();
        response.setUserName("群發(fā)消息模板測試");
        webSocketServer.sendMassMessage(JSONObject.toJSONString(response));
    }
 
    @Data
    @Accessors(chain = true)
    public static class WebsocketResponse {
        private String userId;
        private String userName;
        private int age;
    }
}

5、在線測試地址

websocket 在線測試

6、測試截圖

訪問測試發(fā)送消息:http://localhost:50041//web/test

測試訪問地址:ws://192.168.0.115:50041/webSocket/1   wss://192.168.0.115:50041/webSocket/2

SpringBoot怎么實現(xiàn)WebSocket即時通訊

SpringBoot怎么實現(xiàn)WebSocket即時通訊

SpringBoot怎么實現(xiàn)WebSocket即時通訊

以上就是關(guān)于“SpringBoot怎么實現(xiàn)WebSocket即時通訊”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI