簡體   English   中英

Spring 開機 Websocket 不帶 SockJS

[英]Spring boot Websocket without SockJS

我已經為此苦苦掙扎了至少兩個星期。 我對 websockets 很陌生。 我對 rest 端點有很好的經驗。

我的用例很簡單。 客戶端啟動 websocket 連接,向服務器發送一些信息,服務器使用該信息,並每隔 5 秒定期向客戶端發送一些信息。 我按照這里的教程進行操作 - https://spring.io/guides/gs/messaging-stomp-websocket/它按照說明完美運行。 按照上面的教程,客戶端發起一個 http 請求,升級為 websocket。

就我而言,前端是一個 angular 10 應用程序,前端開發人員更喜歡使用rxjs/websocket並且不想使用SockJS client ,因為他確信我們不必支持任何舊版瀏覽器,這是我被擊中的地方。 顯然rxjs/websocketws://協議中需要 url 。

從下面的代碼片段中,我認為我的等效 ws 協議是ws://localhost:8080/test但是,它似乎不起作用。 我不確定出了什么問題。 任何幫助是極大的贊賞!

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
{

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config)
    {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/ws/");
    

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry)
    {
        registry.addEndpoint("/test");
    }

}

從教程中,我更改了app.js ,如下進行測試。

function connect() {
    // var socket = new SockJS('http://localhost:8080/test'); This works perfectly
    // stompClient = Stomp.over(socket);
    ws = new WebSocket('ws://localhost:8080/test');
    stompClient = Stomp.client(ws);

    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/' + $("#site").val(), function (message) {
            showMessageSentFromServer(JSON.stringify(message.body));
        });
    });
}

當我打開 chrome 的開發者工具並檢查時,我看到 websocket 連接已建立並升級,或者這就是我所看到的。 但是,在控制台中,我看到如下錯誤日志。 我不確定出了什么問題。

網絡截圖:

在此處輸入圖像描述

控制台故障日志:

stomp.min.js:8 Uncaught DOMException: Failed to construct 'WebSocket': The URL '[object WebSocket]' is invalid.
    at Object.client (http://localhost:8080/webjars/stomp-websocket/stomp.min.js:8:7229)
    at connect (http://localhost:8080/app.js:18:25)
    at HTMLButtonElement.<anonymous> (http://localhost:8080/app.js:54:9)
    at HTMLButtonElement.dispatch (http://localhost:8080/webjars/jquery/jquery.min.js:3:10315)
    at HTMLButtonElement.q.handle (http://localhost:8080/webjars/jquery/jquery.min.js:3:8342)

現在長話短說,我設法通過刪除withSockJS()在服務器端禁用了 SockJs。 那么我等效的ws協議 URL 是什么?

此外,除此之外,我面臨的另一個挑戰是,如何根據來自客戶端的輸入設置一個預定進程,該進程可以將消息發送到客戶端訂閱的 websocket 主題。 我知道使用@Scheduled注釋設置計划進程很容易。 但在我的情況下,我想要一些來自客戶端的輸入,這些輸入是計划過程中所必需的。

另外,請分享您擁有的任何資源或示例,以解釋如何使用rxjs實現 websocket 踩踏客戶端訂閱主題

我能夠通過進行兩個簡單的更改來解決這個問題。

  1. 我通過向WebSocketConfig添加兩個端點(如下所示)使我的后端同時支持wshttp協議 - 一個使用 sockjs,另一個不sockjs ,如下所示,這使我的后端在支持兩種協議建立websocket方面更加靈活聯系。 我不知道為什么 spring 文檔或其他任何地方都沒有提到這一點。 或許,人們認為它是隱含的!
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
{

        @Override
        public void configureMessageBroker(MessageBrokerRegistry config)
        {
                config.enableSimpleBroker("/topic");
                config.setApplicationDestinationPrefixes("/ws/");
        }

        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry)
        {
                registry.addEndpoint("/test"); // This will allow you to use ws://localhost:8080/test to establish websocket connection
                registry.addEndpoint("/test").withSockJS(); // This will allow you to use http://localhost:8080/test to establish websocket connection
        }

}
  1. 正如@arturgrzesiak在之前的評論中指出的那樣,傳遞給Stomp.client(url)的參數中有一個錯誤,我很傻,傳遞的是ws object 而不是普通的url
stompClient = Stomp.client('ws://localhost:8080/test');

最后,

如果有人想使用SockJS客戶端連接,他們可以使用連接

var socket = new SockJS('http://localhost:8080/test');
stompClient = Stomp.over(socket);

如果有人只想使用普通的Websocket object 進行連接,請使用以下內容。

stompClient = Stomp.client('ws://localhost:8080/test');

我發布了這個解決方案,因為這對那些有類似痛苦經歷的人很有用,他們可能會覺得它很有用。

如評論中所述:

來自 stomp 文檔: var url = "ws://localhost:15674/ws"; var client = Stomp.client(url); - 你應該只傳遞 url 字符串,而不是已經創建的 websocket object。

您可以嘗試使用var client = Stomp.overWS('ws://localhost:61614');

參考: https://github.com/jmesnil/stomp-websocket

我不是專家,但我雖然所有 WebSocket URI 都使用方案 ws: 或 wss: 以獲得安全的 WebSocket。 要更熟悉 WebSockets,您應該看看Websockets 是如何工作的? .

當我開始使用 Websockets 時,我從Androidhive 學到了很多東西。 使用 Sockets 構建群聊應用程序

我不太習慣 spring Websockets 但在過去我使用 Java EE 時它相對簡單。 您所要做的就是使用帶注釋的@ServerEndpoint 配置服務器端點。 在那里你可以使用帶有注釋的函數

@OnMessage
public String onMessage(String message, Session session) {
    ...
}

@OnOpen
public void onOpen(Session session) {
    ...
    // Here you can start a session handler
    // which will send message every 5 sec or so.
    s = new SessionHandler(session, id);
    s.start();
}

@OnClose
public void onClose(Session session) {
    ...
}

這是您發送消息的方式

public void send(String msg) throws IOException {
    session.getBasicRemote().sendText(msg);
    // session.getBasicRemote().flushBatch(); 
}

這是javascript側,

var wsUri = "ws://" + (document.location.hostname === "" ? "localhost" : document.location.hostname) + ":" +
            (document.location.port === "" ? "80" : document.location.port);

var websocket;
function connect() {
    websocket = new WebSocket(wsUri);

    websocket.onopen = function (evt) {
        onOpen(evt);
    };
    websocket.onmessage = function (evt) {
        onMessage(evt);
    };
    websocket.onerror = function (evt) {
        onError(evt);
    };

    websocket.onclose = function (evt) {
        onClose(evt);
    };
}

connect();

我知道這主要集中在 Java EE 但也許你可以考慮使用 Java EE,它不再那么糟糕了。 如果您有興趣,請查看這個更深入的示例How to build applications with the WebSocket API for Java EE 和 Jakarta EE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM