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

springboot項(xiàng)目跟JavaScript簡(jiǎn)單websocket使用方式

 更新時(shí)間:2026年01月31日 08:59:40   作者:心之語(yǔ)歌  
WebSocket是一種實(shí)現(xiàn)客戶端與服務(wù)器全雙工通信的協(xié)議,它提供了低延遲和雙向數(shù)據(jù)傳輸,適用于實(shí)時(shí)應(yīng)用,通過(guò)Java的Spring框架輕松集成WebSocket,實(shí)現(xiàn)服務(wù)器端與客戶端的實(shí)時(shí)通信

websocket 簡(jiǎn)紹

WebSocket 是一種在單個(gè) TCP 連接上進(jìn)行全雙工通信的協(xié)議。WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。

在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。

WebSocket 的優(yōu)勢(shì)包括

  • 全雙工通信:允許服務(wù)器主動(dòng)向客戶端發(fā)送信息,同時(shí)也能夠提供客戶端到服務(wù)器的低延遲通信。
  • 減少帶寬消耗:一旦建立連接之后,通信開銷很小,因?yàn)椴恍枰狧TTP頭部。

創(chuàng)建更豐富的交互體驗(yàn):實(shí)時(shí)更新數(shù)據(jù)的能力,使得應(yīng)用能夠更加流暢地響應(yīng)用戶的動(dòng)作

可以通過(guò) JavaScript 的 WebSocket 對(duì)象來(lái)創(chuàng)建一個(gè) WebSocket 連接。

var ws = new WebSocket('ws://localhost:8080');

JavaScript 設(shè)置

處理事件

WebSocket 對(duì)象提供了幾個(gè)事件處理器來(lái)處理連接的狀態(tài)變化:

  • open:連接成功建立時(shí)觸發(fā)。
  • message:接收到消息時(shí)觸發(fā)。
  • error:發(fā)生錯(cuò)誤時(shí)觸發(fā)。
  • close:連接關(guān)閉時(shí)觸發(fā)。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Example</title>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const socket = new WebSocket('ws://localhost:8080/websocket');

            socket.onopen = function (event) {
                console.log('WebSocket connection established.');
            };

            socket.onmessage = function (event) {
                console.log('Received from server:', event.data);
            };

            socket.onclose = function (event) {
                console.log('WebSocket connection closed.');
            };

            socket.onerror = function (error) {
                console.error('WebSocket error:', error);
            };

            function sendMessage() {
                let message = document.getElementById('message').value;
                socket.send(message);
                console.log('Sent message:', message);
            }
        });
    </script>
</head>
<body>
    <input type="text" id="message" placeholder="Type your message here">
    <button onclick="sendMessage()">Send Message</button>
</body>
</html>

確保你的服務(wù)器端已正確配置,并且能夠接收來(lái)自客戶端的連接請(qǐng)求。

使用HTTPS和WSS(加密的WebSocket)可以提高安全性,特別是在生產(chǎn)環(huán)境中。

如果你的服務(wù)器部署在不同的域上,請(qǐng)確保服務(wù)器配置允許跨域訪問(wèn)。

Java 服務(wù)端設(shè)置

導(dǎo)jar包

通過(guò) maven 導(dǎo)入 spring boot 中 集成的 websocket jar 包

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

創(chuàng)建WebSocket端點(diǎn)

@EnableWebSocket

@EnableWebSocket 是 Spring 框架中的一個(gè)注解,用于啟用 WebSocket 支持。當(dāng)一個(gè)類被標(biāo)記為此注解時(shí),Spring 會(huì)自動(dòng)配置必要的組件來(lái)處理 WebSocket 請(qǐng)求。這個(gè)注解通常應(yīng)用在一個(gè)配置類上,該類負(fù)責(zé)設(shè)置 WebSocket 的處理邏輯。

registerWebSocketHandlers

  • registerWebSocketHandlers 是 Spring WebSocket 框架中的一個(gè)重要方法,它用來(lái)注冊(cè) WebSocket 處理器(WebSocketHandler)。這個(gè)方法是 WebSocketConfigurer 接口中定義的一個(gè)抽象方法,需要在你的配置類中實(shí)現(xiàn)。通過(guò)這個(gè)方法,你可以指定哪些路徑映射到特定的 WebSocket 處理器,并可以配置其他相關(guān)選項(xiàng)。
  • addHandler 方法:接受兩個(gè)參數(shù),一個(gè)是 WebSocketHandler 的實(shí)例,另一個(gè)是 WebSocket 終結(jié)點(diǎn)的 URL 映射。
  • setAllowedOrigins 方法:指定哪些源(域名)可以訪問(wèn)你的 WebSocket 終結(jié)點(diǎn)。如果設(shè)置為 “*”,則表示任何源都可以訪問(wèn)。
  • withSockJS 方法:這是一個(gè)可選的配置項(xiàng),用于啟用 SockJS,它是一種兼容性更好的 WebSocket 實(shí)現(xiàn),能夠在不支持原生 WebSocket 的瀏覽器上使用其他傳輸方式(如長(zhǎng)輪詢)。

接下來(lái),定義一個(gè)WebSocket處理器類,并配置一個(gè)端點(diǎn)來(lái)接受WebSocket連接:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    private final WebSocketHandler webSocketHandler;

    public WebSocketConfig(WebSocketHandler webSocketHandler) {
        this.webSocketHandler = webSocketHandler;
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/websocket").setAllowedOrigins("*");
    }
}

這里我們定義了一個(gè)WebSocket配置類,并注冊(cè)了WebSocket處理器。/websocket 是WebSocket的端點(diǎn)路徑。

實(shí)現(xiàn)WebSocket處理器

afterConnectionEstablished

void afterConnectionEstablished(WebSocketSession session) throws Exception;
  • afterConnectionEstablished 是 WebSocketHandler 接口中定義的一個(gè)方法,它會(huì)在 WebSocket 連接成功建立之后被調(diào)用。這個(gè)方法為你提供了一個(gè)機(jī)會(huì)來(lái)執(zhí)行一些初始化操作,例如記錄連接信息、將連接加入到一個(gè)管理連接的集合中,或者發(fā)送初始消息給客戶端。
  • WebSocketSession session —— 表示新建立的 WebSocket 會(huì)話。
  • Exception —— 如果處理過(guò)程中出現(xiàn)任何異常,可以拋出

afterConnectionClosed

void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception;
  • afterConnectionClosed 是 WebSocketHandler 接口中定義的一個(gè)方法,它會(huì)在 WebSocket 連接關(guān)閉時(shí)被調(diào)用。這個(gè)方法允許你在連接關(guān)閉后執(zhí)行一些清理操作,例如從會(huì)話管理器中移除會(huì)話、記錄關(guān)閉事件或者發(fā)送通知給其他客戶端。
  • WebSocketSession session:表示已關(guān)閉的 WebSocket 會(huì)話。
  • CloseStatus status:表示關(guān)閉狀態(tài)的原因。CloseStatus 是一個(gè)枚舉類型,提供了標(biāo)準(zhǔn)的關(guān)閉碼和關(guān)閉原因,例如 NORMAL_CLOSURE(正常關(guān)閉)、GOING_AWAY(離開)、PROTOCOL_ERROR(協(xié)議錯(cuò)誤)等。
  • 拋出:Exception —— 如果處理過(guò)程中出現(xiàn)任何異常,可以拋出。

handleTextMessage

void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception;
  • handleTextMessage 是 WebSocketHandler 接口中定義的一個(gè)方法,用于處理從客戶端接收到的文本消息。當(dāng)客戶端發(fā)送文本消息時(shí),這個(gè)方法會(huì)被調(diào)用。對(duì)于二進(jìn)制消息,則會(huì)調(diào)用 handleBinaryMessage 方法。
  • WebSocketSession session:表示當(dāng)前的 WebSocket 會(huì)話。
  • TextMessage message:包含從客戶端接收到的文本消息。
  • 拋出:Exception —— 如果處理過(guò)程中出現(xiàn)任何異常,可以拋出
  • 現(xiàn)在我們需要實(shí)現(xiàn)一個(gè)WebSocket處理器類來(lái)處理連接事件:
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.concurrent.ConcurrentHashMap;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketHandler extends TextWebSocketHandler {

    private static final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
		public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        String id = session.getId();
        sessions.put(id, session);
        System.out.println("WebSocket connection established with session ID: " + id);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        String id = session.getId();
        sessions.remove(id);
        System.out.println("WebSocket connection closed with session ID: " + id);
    }

    public void sendMessageToSession(String sessionId, String message) {
        WebSocketSession session = sessions.get(sessionId);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void broadcastMessage(String message) {
        for (WebSocketSession session : sessions.values()) {
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

現(xiàn)在我們可以使用WebSocketHandler類中的sendMessageToSession或broadcastMessage方法來(lái)發(fā)送數(shù)據(jù)給前端。

發(fā)送給特定會(huì)話:如果想要向特定的客戶端發(fā)送消息,可以使用sendMessageToSession方法。你需要知道客戶端的會(huì)話ID。

webSocketHandler.sendMessageToSession(sessionId, "Hello, client!");

廣播消息:如果你想向所有已連接的客戶端廣播消息,可以使用broadcastMessage方法

webSocketHandler.broadcastMessage("Hello, everyone!")

注銷WebSocket連接

要在Java后端注銷WebSocket連接,可以通過(guò)調(diào)用 WebSocketHandler 類中的 removeSession 方法來(lái)實(shí)現(xiàn)。例如,你可以從HTTP請(qǐng)求或其他服務(wù)中調(diào)用此方法:

@GetMapping("/logout/{sessionId}")
public ResponseEntity<String> logout(@PathVariable String sessionId) {
    WebSocketHandler handler = new WebSocketHandler(); // 或者通過(guò)依賴注入獲取
    handler.removeSession(sessionId);
    return ResponseEntity.ok("Session " + sessionId + " has been closed.");
}

自己定義一個(gè) 固定id 方便使用

前端 JavaScript 代碼

  • 創(chuàng)建WebSocket連接:在DOM加載完成后,創(chuàng)建一個(gè)WebSocket連接。
  • 發(fā)送握手消息:在連接建立后,發(fā)送一個(gè)包含固定ID的握手消息。
  • 處理接收到的消息:設(shè)置消息接收處理函數(shù),用于接收后端發(fā)送的數(shù)據(jù)。

后端 Java 代碼

  • 配置WebSocket處理器:配置WebSocket處理器,注冊(cè)WebSocket路徑。
  • 處理握手消息:接收前端發(fā)送的握手消息,并根據(jù)消息內(nèi)容保存客戶端ID與WebSocket會(huì)話的映射。
  • 發(fā)送消息:提供方法根據(jù)客戶端ID發(fā)送消息。

前端 javascript

<!DOCTYPE html>
<html l	ang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Client Example</title>
</head>
<body>
    <input type="text" id="messageInput" placeholder="Enter your message here">
    <button id="sendButton">Send Message</button>
    <div id="log"></div>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const socket = new WebSocket('ws://example.com/websocket');

            socket.onopen = function (event) {
                console.log('WebSocket connection established.');

                // 固定的客戶端ID
                const clientId = 'client-123';

                // 發(fā)送握手消息
                socket.send(JSON.stringify({
                    type: 'handshake',
                    clientId: clientId,
                    message: 'Hello, server!'
                }));
            };

            socket.onmessage = function (event) {
                console.log('Received from server:', event.data);
                document.getElementById('log').textContent += 'Received from server: ' + event.data + '\n';
            };

            socket.onclose = function (event) {
                console.log('WebSocket connection closed.');
                document.getElementById('log').textContent += 'WebSocket connection closed.\n';
            };

            socket.onerror = function (error) {
                console.error('WebSocket error:', error);
                document.getElementById('log').textContent += 'WebSocket error: ' + error + '\n';
            };

            document.getElementById('sendButton').addEventListener('click', function () {
                let message = document.getElementById('messageInput').value;
                if (socket.readyState === WebSocket.OPEN) {
                    socket.send(message);
                    document.getElementById('log').textContent += 'Sent message: ' + message + '\n';
                } else {
                    alert('WebSocket connection is not open.');
                }
            });
        });
    </script>
</body>
</html>

java 服務(wù)器端配置

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.socket.HandshakeMessage;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class WebSocketHandler extends TextWebSocketHandler {

    private static final Map<String, WebSocketSession> clientSessions = new ConcurrentHashMap<>();
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        String sessionId = session.getId();
        System.out.println("WebSocket connection established with session ID: " + sessionId);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        HandshakeMessage handshakeMessage = objectMapper.readValue(payload, HandshakeMessage.class);

        if ("handshake".equals(handshakeMessage.getType())) {
            String clientId = handshakeMessage.getClientId();
            String sessionId = session.getId();

            // 存儲(chǔ)clientId與sessionId的映射關(guān)系
            clientSessions.put(clientId, session);

            // 可以選擇回復(fù)客戶端確認(rèn)握手成功的消息
            session.sendMessage(new TextMessage("Handshake successful"));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        String sessionId = session.getId();
        System.out.println("WebSocket connection closed with session ID: " + sessionId);

        // 移除會(huì)話
        clientSessions.values().removeIf(s -> s.getId().equals(sessionId));
    }

    public void sendMessageToClient(String clientId, String message) {
        WebSocketSession session = clientSessions.get(clientId);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 定義握手消息模型
    private static class HandshakeMessage {
        private String type;
        private String clientId;
        private String message;

        // Getters and setters
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java參數(shù)傳遞之值傳遞和引用傳遞

    java參數(shù)傳遞之值傳遞和引用傳遞

    這篇文章主要介紹了java參數(shù)傳遞之值傳遞和引用傳遞,引用了兩個(gè)代碼實(shí)例來(lái)講解,有感興趣的同學(xué)可以研究下
    2021-02-02
  • springmvc字符編碼過(guò)濾器CharacterEncodingFilter的使用

    springmvc字符編碼過(guò)濾器CharacterEncodingFilter的使用

    這篇文章主要介紹了springmvc字符編碼過(guò)濾器CharacterEncodingFilter的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2021-08-08
  • Java文件批量重命名批量提取特定類型文件

    Java文件批量重命名批量提取特定類型文件

    這篇文章主要介紹了Java文件批量重命名批量提取特定類型文件的相關(guān)資料
    2016-08-08
  • K均值聚類算法的Java版實(shí)現(xiàn)代碼示例

    K均值聚類算法的Java版實(shí)現(xiàn)代碼示例

    這篇文章主要介紹了K均值聚類算法的Java版實(shí)現(xiàn)代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • IDEA使用Lombok簡(jiǎn)化POJO代碼的示例

    IDEA使用Lombok簡(jiǎn)化POJO代碼的示例

    今天小編就為大家分享一篇關(guān)于IDEA使用Lombok簡(jiǎn)化POJO代碼的示例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Spring Cloud Alibaba 全解析

    Spring Cloud Alibaba 全解析

    本文給大家介紹Spring Cloud Alibaba全解析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2026-02-02
  • Spring?Boot整合Zookeeper實(shí)現(xiàn)分布式鎖的場(chǎng)景分析

    Spring?Boot整合Zookeeper實(shí)現(xiàn)分布式鎖的場(chǎng)景分析

    這篇文章主要介紹了Spring?Boot整合Zookeeper實(shí)現(xiàn)分布式鎖,zk實(shí)現(xiàn)分布式鎖完全是依靠zk節(jié)點(diǎn)類型當(dāng)中的臨時(shí)序號(hào)節(jié)點(diǎn)來(lái)實(shí)現(xiàn)的,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 淺談一下Java中的堆和棧

    淺談一下Java中的堆和棧

    這篇文章主要介紹了一下Java中的堆和棧,Java數(shù)據(jù)類型在執(zhí)行過(guò)程中存儲(chǔ)在兩種不同形式的內(nèi)存中:棧和堆,它們通常由運(yùn)行Java虛擬機(jī)(JVM)的底層平臺(tái)維護(hù),需要的朋友可以參考下
    2023-04-04
  • springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解

    springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解

    這篇文章主要介紹了springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 詳解JFX11+IDEA跨平臺(tái)打包發(fā)布的完美解決辦法

    詳解JFX11+IDEA跨平臺(tái)打包發(fā)布的完美解決辦法

    這篇文章主要介紹了詳解JFX11+IDEA跨平臺(tái)打包發(fā)布的完美解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論

元朗区| 建宁县| 淳化县| 闸北区| 青冈县| 谢通门县| 清新县| 尤溪县| 南郑县| 兴安县| 九台市| 罗定市| 兰坪| 鄄城县| 民乐县| 乌拉特中旗| 铅山县| 砚山县| 肃北| 溧阳市| 舞阳县| 白朗县| 翁牛特旗| 荔浦县| 民乐县| 石河子市| 绥棱县| 阿城市| 新安县| 濮阳县| 衡山县| 宁陵县| 高青县| 象山县| 阳城县| 澳门| 石棉县| 西城区| 广西| 六枝特区| 禄丰县|