会话关闭时使用Spring WebSocketConnectionManager的正确方法是什么

时间:2018-08-16 09:22:12

标签: spring spring-boot websocket spring-websocket

我使用Spring的WebSocketConnectionManager处理WebSockets。有时连接关闭,我必须重新连接。但是我没有找到合适的解决方案。我可以使用WebSocketConnectionManager进行还原(重新连接)会话吗?在sources I see中,该连接通过以下代码建立:

if constexpr (std::is_same<...>())

当我的spring boot应用程序启动时,我正在使用此管理器:

@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);
        }
    });
}

但是当连接关闭时我该怎么办?我试图从openConnection()复制一段代码,并使用它直接在webSocketHandler中更新会话,并且可以正常工作。但这似乎是肮脏的解决方法。

有人知道如何正确执行吗?谢谢。

2 个答案:

答案 0 :(得分:3)

在我的一个项目中,我遇到了类似的情况。 因此,我依靠在连接管理器类中使用start()和stop()方法来访问WebSocketManager作为bean。 有时我为websocketserverwebsocketclient创建了一个示例项目。刚刚添加了重新连接功能。

此外,我并没有在每次关闭连接时都重新连接。仅在close status 1006(异常关闭),1011(内部错误)和1012(服务重新启动)上。

该项目可以直接下载并运行。

答案 1 :(得分:0)

我认为您不需要直接在openConnection中复制webSocketHandler函数。您应该能够重新使用openConnection函数并从WebSocketConnectionManager内部捕获afterConnectionClose事件。

我认为您的做法正确。不幸的是,由于在WebSocketConnectionManager内不存在任何处理WebSocket“关闭”事件的事实,因此我认为这不是一个肮脏的解决方法。

在WebSocketConnectionManager的文档中,我看到以下摘录:

  

一个提供了URI的WebSocket连接管理器,一个WebSocketClient,   和WebSocketHandler,通过以下方式连接到WebSocket服务器   ConnectionManagerSupport.start()和ConnectionManagerSupport.stop()   方法。如果将ConnectionManagerSupport.setAutoStartup(boolean)设置为   是的,这将在春季时自动完成   刷新ApplicationContext。

与Spring的WebSocketConnectionManager等效的JavaScript的WebSocket onClose似乎是afterConnectionClosed,您可以在WebSocketHandler的文档中找到它。实际上,afterConnectionClosed上的文档说:

  

afterConnectionClosed-在任一侧关闭WebSocket连接后调用,   或发生运输错误后。尽管会议可能   在技​​术上仍然是开放的,具体取决于底层的实现,   此时不鼓励发送消息,并且很可能不会   成功。

因此,我认为您的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中,我使用reconnecting-websocket,因此我的直觉告诉我,如果该功能尚不存在,则基本上需要在Spring中实现。或如answer建议使用JavaScript一样,您需要从WebSocket捕获onClose事件并重新连接。

有趣的是,Spring repo中有一些名为onClose的方法,所以也许这个问题需要重新研究。