如何将concurrentwebsocketsessiondecorator与自定义websockethandler一起使用

ejk8hzay  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(529)

我有一个自定义websocket处理程序(用于自定义子协议),按常规方式注册:

public class WSConfig implements WebSocketConfigurer {

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

内部 CustomProtocolHandler 继承自的所有方法 WebSocketHandler (例如。 afterConnectionEstablished , handleMessage 等)接收 WebSocketSession 这不是线程安全的。官方教程说 ConcurrentWebSocketSessionDecorator 可以用来防止并发写操作,但是当我的自定义处理程序被命中时,就已经来不及 Package 会话了。

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 (和我的一样 WebSocketHandler 以及 SubProtocolCapable )我希望我能用它作为基础,但我要创造 SubProtocolWebSocketHandler 我需要 MessageChannel 它来自spring消息。我既不使用spring消息,也不知道如何获得 MessageChannel . 我应该实现一个自定义的吗?
那么,情况如何 ConcurrentWebSocketSessionDecorator 是否打算使用?我希望有一种方法可以将会话 Package 逻辑注册到 webSocketHandlerRegistry ,但是没有。我唯一的想法就是保持另一个 ConcurrentHashMap 这将原始会话(或其id)Map到 Package 器,但这很糟糕,我认为我不需要更多的状态来管理和清理。

j13ufse2

j13ufse21#

最后我做了我自己的版本 PerConnectionWebSocketHandler 与原来的一样,它维护一个会话到处理程序的Map,但我的Map将处理程序 Package 到一个holder中,该holder还包含一个修饰的会话供处理程序使用。
原版 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
    }
}

相关问题