[英]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/websocket
在ws://
協議中需要 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 踩踏客戶端訂閱主題
我能夠通過進行兩個簡單的更改來解決這個問題。
WebSocketConfig
添加兩個端點(如下所示)使我的后端同時支持ws
和http
協議 - 一個使用 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
}
}
@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');
我不是專家,但我雖然所有 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.