Как правильно использовать Spring WebSocketConnectionManager при закрытии сеансов

Я использую Spring WebSocketConnectionManager для работы с WebSockets. Иногда соединение закрывается, и мне приходится подключаться заново. Но я не нашел для этого подходящего решения. Могу ли я использовать WebSocketConnectionManager для восстановления (повторного подключения) сеанса? В источники я вижу это соединение устанавливается с помощью следующего кода:

@Override
protected void openConnection() {
    if (logger.isInfoEnabled()) {
        logger.info("Connecting to WebSocket at " + getUri());
    }

    ListenableFuture<WebSocketSession> future =
            this.client.doHandshake(this.webSocketHandler, this.headers, getUri());

    future.addCallback(new ListenableFutureCallback<WebSocketSession>() {
        @Override
        public void onSuccess(@Nullable WebSocketSession result) {
            webSocketSession = result;
            logger.info("Successfully connected");
        }
        @Override
        public void onFailure(Throwable ex) {
            logger.error("Failed to connect", ex);
        }
    });
}

И я использую этот менеджер, когда мое приложение весенней загрузки запускается с:

WebSocketConnectionManager connectionManager = new WebSocketConnectionManager(
    new StandardWebSocketClient(), webSocketHandler, "wss://localhost:8080/ws/");

connectionManager.start();

Но что мне делать, когда соединение закрывается? Я попытался скопировать фрагмент кода из openConnection () и использовать его для обновления сеанса непосредственно в webSocketHandler, и он работает. Но это похоже на грязный обходной путь.

Кто-нибудь знает, как это правильно делать? Спасибо.

8
0
1 540
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не думаю, что вам нужно копировать функцию openConnection прямо в webSocketHandler. Вы должны иметь возможность повторно использовать функцию openConnection и захватывать событие afterConnectionClose изнутри WebSocketConnectionManager.

Я думаю, вы на правильном пути. К сожалению, я не думаю, что это грязный обходной путь из-за того, что внутри WebSocketConnectionManager ничего не существует для обработки событий WebSocket «при закрытии».

В документации для WebSocketConnectionManager я вижу этот отрывок:

A WebSocket connection manager that is given a URI, a WebSocketClient, and a WebSocketHandler, connects to a WebSocket server through ConnectionManagerSupport.start() and ConnectionManagerSupport.stop() methods. If ConnectionManagerSupport.setAutoStartup(boolean) is set to true this will be done automatically when the Spring ApplicationContext is refreshed.

Эквивалент JavaScript WebSocket onClose для Spring WebSocketConnectionManager кажется afterConnectionClosed, который вы можете найти в документации для WebSocketHandler. Действительно, в документации на afterConnectionClosed говорится:

afterConnectionClosed - Invoked after the WebSocket connection has been closed by either side, or after a transport error has occurred. Although the session may technically still be open, depending on the underlying implementation, sending messages at this point is discouraged and most likely will not succeed.

Поэтому я думаю, что ваш код Spring должен включать что-то вроде псевдокода ниже:

    afterConnectionClosed(WebSocketSession result, CloseStatus closeStatus) {
        // Spring code here to delay retry for re-connecting to WebSocket. 
        openConnection()
    };

Эквивалент в JavaScript:

     ws.onclose = function(){
        // Try to reconnect in 5 seconds
        setTimeout(function(){start(websocketServerLocation)}, 5000);
    };

Надеюсь, кто-нибудь с опытом Spring сможет прийти и отредактировать этот пост и указать, где я прав, а где ошибаюсь. Я не использую Spring, но у меня есть опыт работы с WebSocket. В JavaScript я использую переподключение-websocket, поэтому интуиция подсказывает мне, что вам, по сути, нужно реализовать эту функцию в Spring, если она еще не существует. Или, как предлагает этот отвечать для JavaScript, вам нужно захватить событие onClose из WebSocket и повторно подключиться.

Интересно, что в Весеннее репо есть несколько методов с именем onClose, поэтому, возможно, этот вопрос требует повторного рассмотрения.

Ответ принят как подходящий

В одном из своих проектов я столкнулся с похожей ситуацией. Итак, я прибег к использованию методов start () и stop () с доступом к WebSocketManager в качестве bean-компонента в классе диспетчера соединений. Некоторое время назад я создал образец проекта для веб-сервер и websocketclient. Просто добавили к нему функцию переподключения.

Кроме того, я не переподключался при каждом закрытии соединения. Только на закрытый статус 1006 (аварийное закрытие), 1011 (внутренняя ошибка) и 1012 (перезапуск службы).

Проект можно сразу скачать и запустить.

Другие вопросы по теме