如何将 ConcurrentWebSocketSessionDecorator 与自定义 WebSocketHandler 一起使用

卡卡奥

我有一个自定义的 WebSocket 处理程序(用于自定义子协议),以通常的方式注册:

public class WSConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry
                .addHandler(new PerConnectionWebSocketHandler(CustomProtocolHandler.class), endpointUrl);
    }
}

CustomProtocolHandler所有继承自WebSocketHandler(例如afterConnectionEstablishedhandleMessage等)的方法中接收WebSocketSession不是线程安全的。官方教程说ConcurrentWebSocketSessionDecorator可以用来防止并发写入,但是当我的自定义处理程序被命中时,包装会话已经太晚了。

public class CustomProtocolHandler implements WebSocketHandler, SubProtocolCapable {

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        //This is not safe
        session.sendMessage(...);

        //And this this doesn't make sense
        new ConcurrentWebSocketSessionDecorator(session).sendMessage(...);
    }
}

现在,我看到 Spring 自己的SubProtocolWebSocketHandler(它和我的一样,实现了WebSocketHandlerSubProtocolCapable)确实在内部装饰了会话,我希望我能够将它用作基础,但是要创建SubProtocolWebSocketHandler我需要的MessageChannel来自 spring 消息传递。我既不使用 Spring Messaging,也不知道如何获得MessageChannel. 我应该实施一个自定义的吗?

那么,ConcurrentWebSocketSessionDecorator打算如何使用呢?我希望有一种方法可以用 注册会话包装逻辑webSocketHandlerRegistry,但不是。我唯一的想法是维护另一个ConcurrentHashMap将原始会话(或其 ID)映射到包装器的想法,但这太可怕了,我认为我不需要更多状态来管理和清理。

卡卡奥

我最终制作了自己的版本PerConnectionWebSocketHandler,就像原始版本一样,维护一个会话到处理程序的映射,但我的将处理程序包装到一个持有者中,该持有者还包含一个装饰会话供处理程序使用。

原来的PerConnectionWebSocketHandler样子是这样的:

public class PerConnectionWebSocketHandler implements WebSocketHandler, BeanFactoryAware {

    private final Map<WebSocketSession, WebSocketHandler> handlers = new ConcurrentHashMap<>();

    ...

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        WebSocketHandler handler = this.provider.getHandler();
        this.handlers.put(session, handler);
        handler.afterConnectionEstablished(session);
    }
}

我的现在看起来像这样:

public class CustomPerConnectionWebSocketHandler implements WebSocketHandler {

    private final Map<WebSocketSession, HandlerWrapper> handlers = new ConcurrentHashMap<>();

    ...

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        WebSocketHandler handler = ...;
        //Here's a chance to decorate the session as needed
        WebSocketSession decoratedSession = new ConcurrentWebSocketSessionDecorator(session, sendTimeLimit, sendBufferSizeLimit);
        HandlerWrapper wrapper = new HandlerWrapper(handler, decoratedSession);
        this.handlers.put(session, wrapper);
        wrapper.afterConnectionEstablished();
    }


    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
         //Delegate all the calls in this fashion
         handlers.get(session).handleMessage(message);
    }

    ...

    private static class HandlerWrapper {

        private final WebSocketHandler handler;
        private final WebSocketSession session;

        HandlerWrapper(WebSocketHandler handler, WebSocketSession session) {
            this.handler = handler;
            this.session = session;
        }

        void afterConnectionEstablished() throws Exception {
            handler.afterConnectionEstablished(session);
        }

        void handleMessage(WebSocketMessage<?> message) throws Exception {
            handler.handleMessage(session, message);
        }

        ... //Other delegating methods
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将Spring REST Projections与自定义控制器一起使用

如何将 Firebase 存储与自定义服务器一起使用?

如何将boost :: assign与扩展STL容器的自定义容器一起使用?

如何将Picasso与用于RecyclerView的自定义适配器一起使用

如何将sklearn Pipeline与自定义功能一起使用?

如何将AWS Cognito与自定义NodeJS服务器一起使用?

如何将dask.dataframe与自定义dsk图一起使用

如何将 lodash sortBy 与自定义订单比较器一起使用

PS7.1-如何将管道链接与自定义功能一起使用?

如何将标准验证数据注释与自定义类型一起使用?

如何将Alamofire与自定义标头一起使用

如何将AngularJS自定义元素与玉一起使用?

如何将azure流量管理与自定义服务url端点一起使用?

如何将MultiDex与自定义Application类一起使用?

如何将字段集与自定义表单一起使用?

如何将Google Cloud Functions与自定义Google Cloud端点一起使用?

如何将unordered_set与自定义结构一起使用?

如何将buildroot与软件包中的自定义更改一起使用

如何将 CMS 与我的自定义网站一起使用

如何将 UserManager 与自定义用户一起使用?

将标识与自定义属性一起使用

将咖啡与自定义EditText一起使用

将SqlCommandProvider与自定义超时一起使用

将%dopar%与自定义函数一起使用

如何使自定义键盘与Swift一起使用

如何将 react-hook-form 与我自定义的 react-date-picker 一起使用?

如何将Spring Websocket与Spring Session自定义HttpSession一起使用,而没有Stomp / SockJS?

如何将Pillow的Image.convert()与自定义调色板一起使用?

如何将Firebase自定义身份验证与openID提供程序一起使用?