最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用?Spring?Boot?搭建?WebSocket?服務(wù)器實(shí)現(xiàn)多客戶端連接

 更新時(shí)間:2024年11月06日 10:31:32   作者:不掉頭發(fā)的阿水  
本文介紹如何使用SpringBoot快速搭建WebSocket服務(wù)器,實(shí)現(xiàn)多客戶端連接和消息廣播,WebSocket協(xié)議提供全雙工通信,SpringBoot通過@ServerEndpoint簡化配置,支持實(shí)時(shí)消息推送,適用于聊天室或通知系統(tǒng)等應(yīng)用場景

在 Web 開發(fā)中,WebSocket 為客戶端和服務(wù)端之間提供了實(shí)時(shí)雙向通信的能力。本篇博客介紹如何使用 Spring Boot 快速搭建一個(gè) WebSocket 服務(wù)器,并支持多客戶端的連接和消息廣播。

1. WebSocket 簡介

WebSocket 是 HTML5 的一種協(xié)議,提供了客戶端和服務(wù)器之間的全雙工通信。通過 WebSocket,客戶端可以與服務(wù)器進(jìn)行持續(xù)連接,不用反復(fù)建立 HTTP 請求,從而降低延遲,提升通信效率。

為什么選擇 Spring Boot 實(shí)現(xiàn) WebSocket?

Spring Boot 簡化了 WebSocket 服務(wù)器的配置與實(shí)現(xiàn),使我們可以更專注于業(yè)務(wù)邏輯開發(fā),且配合 @ServerEndpoint 注解實(shí)現(xiàn)更加清晰。

2. 項(xiàng)目環(huán)境與依賴配置

項(xiàng)目環(huán)境

  • Java 版本:JDK 8+
  • Spring Boot 版本:2.x
  • WebSocket 依賴spring-boot-starter-websocket

Maven 依賴

pom.xml 文件中添加 WebSocket 的依賴:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

3. WebSocket 服務(wù)端代碼實(shí)現(xiàn)

在 Spring Boot 中,我們可以使用 @ServerEndpoint 注解創(chuàng)建 WebSocket 服務(wù)器端。以下是一個(gè)支持多客戶端連接的 WebSocket 實(shí)現(xiàn)。

WebSocket 服務(wù)端代碼解析

創(chuàng)建 MultiClientWebSocket 類,并實(shí)現(xiàn)以下功能:

  • 記錄當(dāng)前在線客戶端數(shù)
  • 支持客戶端連接、斷開、消息接收、群發(fā)等功能
  • 通過 @OnOpen、@OnMessage、@OnClose、@OnError 注解處理連接的各個(gè)生命周期

完整代碼如下:

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * WebSocketConfig
 */
@Component
@ServerEndpoint("/ws/multi")
@Slf4j
public class MultiClientWebSocket {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        log.info("WebSocketConfig: serverEndpointExporter init WebSocketConfig 注入完成");
        return new ServerEndpointExporter();
    }
    /**
     * 記錄當(dāng)前在線連接數(shù)
     */
    private static final AtomicInteger onlineCount = new AtomicInteger(0);
    /**
     * 存放所有在線的客戶端
     */
    private static final Map<String, Session> onlineClients = new ConcurrentHashMap<>();
    @OnOpen
    public void onOpen(Session session) {
        onlineCount.incrementAndGet();
        onlineClients.put(session.getId(), session);
        log.info("有新連接加入:{},當(dāng)前在線客戶端數(shù)為:{}", session.getId(), onlineCount.get());
    }
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("收到客戶端消息:" + message);
        session.getBasicRemote().sendText("服務(wù)器收到消息:" + message);
    }
    @OnClose
    public void onClose(Session session) {
        onlineCount.decrementAndGet(); // 在線數(shù)減1
        onlineClients.remove(session.getId());
        log.info("有一連接關(guān)閉:{},當(dāng)前在線客戶端數(shù)為:{}", session.getId(), onlineCount.get());
    }
    @OnError
    public void onError(Throwable t) {
        log.error("WebSocket 連接出錯(cuò){}", t.getMessage());
    }
    /**
     * 群發(fā)消息
     *
     * @param message 消息內(nèi)容
     */
    public void sendMessage(String message) {
        //log.info("開始給在線的客戶端{(lán)}群發(fā)消息{}",onlineClients,message);
        for (Map.Entry<String, Session> sessionEntry : onlineClients.entrySet()) {
            Session toSession = sessionEntry.getValue();
            log.info("服務(wù)端給客戶端[{}]發(fā)送消息{}", toSession.getId(), message);
            toSession.getAsyncRemote().sendText(message);
        }
    }
}

代碼解析

  • ServerEndpointExporter:Spring Boot 的 WebSocket 配置類,自動(dòng)注冊 @ServerEndpoint 注解聲明的 WebSocket。
  • 在線客戶端管理:使用 ConcurrentHashMap 存儲在線客戶端的 Session,通過 AtomicInteger 記錄當(dāng)前連接數(shù)。
  • 生命周期注解:
    • @OnOpen:當(dāng)客戶端連接時(shí)觸發(fā),增加在線人數(shù)。
    • @OnMessage:當(dāng)收到消息時(shí)觸發(fā),服務(wù)端處理消息。
    • @OnClose:當(dāng)連接關(guān)閉時(shí)觸發(fā),減少在線人數(shù)。
    • @OnError:當(dāng)連接出錯(cuò)時(shí)觸發(fā),記錄錯(cuò)誤日志。
  • 群發(fā)消息:sendMessage 方法遍歷所有在線客戶端的 Session,實(shí)現(xiàn)消息廣播。

4. 啟動(dòng)與測試

啟動(dòng) Spring Boot 項(xiàng)目后,WebSocket 服務(wù)端地址為:ws://localhost:8080/ws/multi。可以使用 WebSocket 測試工具(例如 Apifox或?yàn)g覽器控制臺)測試 WebSocket 通信。

測試步驟

  • 連接 WebSocket:客戶端連接至 ws://localhost:8080/ws/multi
  • 發(fā)送消息:客戶端發(fā)送消息,服務(wù)端接收到消息后回復(fù)。
  • 斷開連接:客戶端斷開連接,服務(wù)端記錄連接關(guān)閉信息。
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.lps.config.MultiClientWebSocket;
import com.lps.domain.R;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * @ClassName: WebSocketControl
 * @Description:
 * @Author: liu
 * @Date: 2024-10-30
 * @Version: 1.0
 **/
@RestController
@RequestMapping("/webSocket")
@RequiredArgsConstructor
public class WebSocketControl {
    private final MultiClientWebSocket multiClientWebSocket;
    @GetMapping("/sendList")
    public R<String> sad() {
        //Guava依賴
        List<String> strList = Lists.newArrayList("發(fā)送", "WebSocket消息","測試");
        String jsonStr = JSONUtil.toJsonStr(strList);
        multiClientWebSocket.sendMessage(jsonStr);
        return R.ok(jsonStr);
    }
}

前端測試demo

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
    <style>
        #status {
            margin-bottom: 10px;
        }
    </style>
    <script>
        let ws;
		function connectWebSocket() {
			// 檢查 WebSocket 是否已連接
			if (ws && ws.readyState === WebSocket.OPEN) {
				console.log('WebSocket 已連接,無需重復(fù)連接。');
				return;
			}
			ws = new WebSocket('ws://localhost:8080/ws/multi');
			ws.onopen = function() {
				console.log('WebSocket 連接已經(jīng)建立。');
				document.getElementById('status').innerText = 'WebSocket 連接已建立。';
				ws.send('Hello, server!');
			};
			ws.onmessage = function(event) {
				console.log('收到服務(wù)器消息:', event.data);
				document.getElementById('messages').innerText += '收到消息:' + event.data + '\n';
			};
			ws.onerror = function(event) {
				console.error('WebSocket 連接出現(xiàn)錯(cuò)誤:', event);
				document.getElementById('status').innerText = 'WebSocket 連接出現(xiàn)錯(cuò)誤。';
			};
			ws.onclose = function() {
				console.log('WebSocket 連接已經(jīng)關(guān)閉。');
				document.getElementById('status').innerText = 'WebSocket 連接已關(guān)閉。';
				ws = null; // 連接關(guān)閉后將 ws 設(shè)置為 null,以便重新連接
			};
		}
        function disconnectWebSocket() {
            if (ws) {
                ws.close();
            }
        }
    </script>
</head>
<body>
    <h1>WebSocket Demo</h1>
    <div id="status">WebSocket 連接狀態(tài)</div>
    <button onclick="connectWebSocket()">連接 WebSocket</button>
    <button onclick="disconnectWebSocket()">斷開 WebSocket</button>
    <pre id="messages"></pre>
</body>
</html>

5. 總結(jié)

通過以上代碼示例,我們可以實(shí)現(xiàn)一個(gè)簡單的 WebSocket 服務(wù)端,支持多客戶端連接和消息廣播。此 WebSocket 服務(wù)端適用于需要實(shí)時(shí)消息推送的應(yīng)用場景,比如聊天室、實(shí)時(shí)通知系統(tǒng)等。

到此這篇關(guān)于使用 Spring Boot 搭建 WebSocket 服務(wù)器實(shí)現(xiàn)多客戶端連接的文章就介紹到這了,更多相關(guān)Spring Boot 搭建 WebSocket 服務(wù)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼

    spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼

    這篇文章主要介紹了spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java實(shí)現(xiàn)mybatis批量插入數(shù)據(jù)到Oracle

    Java實(shí)現(xiàn)mybatis批量插入數(shù)據(jù)到Oracle

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)mybatis批量插入數(shù)據(jù)到Oracle 的相關(guān)資料,需要的朋友可以參考下
    2016-06-06
  • Java9 Stream Collectors新增功能(小結(jié))

    Java9 Stream Collectors新增功能(小結(jié))

    這篇文章主要介紹了Java9 Stream Collectors新增功能(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 詳解java 拼音首字母搜索內(nèi)容功能的示例

    詳解java 拼音首字母搜索內(nèi)容功能的示例

    這篇文章主要介紹了詳解java 拼音首字母搜索內(nèi)容功能的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • java驗(yàn)證用戶是否已經(jīng)登錄 java實(shí)現(xiàn)自動(dòng)登錄

    java驗(yàn)證用戶是否已經(jīng)登錄 java實(shí)現(xiàn)自動(dòng)登錄

    這篇文章主要介紹了java驗(yàn)證用戶是否已經(jīng)登錄,java實(shí)現(xiàn)自動(dòng)登錄,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Java程序中Doc文檔注釋示例教程

    Java程序中Doc文檔注釋示例教程

    這篇文章主要為大家介紹了Java程序中Doc文檔注釋的示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • MyBatis與Spring中的SqlSession詳解

    MyBatis與Spring中的SqlSession詳解

    在MyBatis中,你可以使用SqlSessionFactory來創(chuàng)建SqlSession,使用MyBatis-Spring之后,你不再需要直接使用SqlSessionFactory了,接下來通過示例代碼講解MyBatis與Spring中的SqlSession,需要的朋友可以參考下
    2024-05-05
  • 基于Springboot的高校社團(tuán)管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)

    基于Springboot的高校社團(tuán)管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)

    本文將基于Springboot+Mybatis開發(fā)實(shí)現(xiàn)一個(gè)高校社團(tuán)管理系統(tǒng),系統(tǒng)包含三個(gè)角色:管理員、團(tuán)長、會(huì)員。文中采用的技術(shù)有Springboot、Mybatis、Jquery、AjAX、JSP等,感興趣的可以了解一下
    2022-07-07
  • SpringSecurity中的UserDetailsService深度解析

    SpringSecurity中的UserDetailsService深度解析

    文章介紹了Spring Security中的UserDetailsService接口,它用于自定義用戶認(rèn)證邏輯,通過實(shí)現(xiàn)該接口,可以自定義用戶認(rèn)證過程,文章詳細(xì)解釋了UserDetailsService接口的返回值、方法參數(shù)以及可能出現(xiàn)的異常,如UsernameNotFoundException,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • MyBatis中的properties配置(推薦)

    MyBatis中的properties配置(推薦)

    這篇文章給大家介紹了MyBatis中的properties配置,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-12-12

最新評論

忻城县| 星子县| 鹤峰县| 陆川县| 西青区| 延边| 花莲市| 建瓯市| 丹阳市| 曲麻莱县| 双牌县| 德庆县| 固始县| 仙游县| 蒲城县| 伊宁县| 石家庄市| 新津县| 绥芬河市| 贵德县| 九寨沟县| 崇仁县| 玛纳斯县| 郁南县| 团风县| 洮南市| 阳东县| 应城市| 鄂托克前旗| 革吉县| 宜川县| 崇文区| 保德县| 上高县| 博乐市| 虎林市| 墨竹工卡县| 二手房| 彰化县| 柏乡县| 滦平县|