基于Spring Websockets构建自定义API

6

我需要实现一个自定义的API,使用Websockets进行通信,需要满足以下要求:

  • 使用类似WAMP的自定义子协议
  • 在socket URI中包含路径参数

因此,我有以下问题:

  • Is there any documentation or guides on implementing custom subprotocols in Spring? Protocol requires that exact version must be specified in the Sec-Websocket-Protocol field. Where this field could be read on server side?
  • What is a proper way to pass path parameters into a message handler? I could use ant patterns in handler registration

        @Override 
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(customHandler(), "/api/custom/{clientId}");
        }
    

    but those seems not available at TextWebSocketHandler. I'm solved this for now by extending default HttpSessionHandshakeInterceptor in a following way:

    public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
        private static final UriTemplate URI_TEMPLATE = new UriTemplate("/api/custom/{clientId}");
    
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                       WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
            Map<String, String> segments = URI_TEMPLATE.match(request.getURI().getPath());
            attributes.put("CLIENTID", segments.get("clientId"));
    
            return super.beforeHandshake(request, response, wsHandler, attributes);
        }
    }
    

    and then accessing it in TextWebSocketHandler:

    public class CustomHandler extends TextWebSocketHandler {
    
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            super.handleTextMessage(session, message);
    
            String clientId = session.getAttributes().get("CLIENTID");
    
            ...
    
            session.sendMessage(response);
        }
    
    }
    

    but this method, in my opinion, is a bit clunky. Is there more proper way to solve this?

感谢您的选择。

你找到更好的解决方案了吗? - Elyran
1个回答

2
我能给出的最好建议是,遵循内置的子协议支持示例——从SubProtocolWebSocketHandler开始,以及它委托的SubProtocolHandler,包括StompSubProtocolHandler实现。 SubProtocolWebSocketHandler 还与“clientInbound”和“clientOutbound”通道相连接,这些通道用于形成处理流程并提供线程边界。
对于STOMP的处理流程http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-message-flow有一个描述,其中包括将消息委派给带注释的控制器和/或消息代理,后者也可以将消息发送回下游客户端。
基本上,StompSubProtocolHandler用于将WebSocketMessage和Spring Message之间的内容进行协议特定的转换。这样,控制器、消息代理或任何其他消费者都可以从客户端入站通道接收消息,而与WebSocket传输层分离且不知情。许多围绕构建、发送和处理此类子协议消息的设施旨在支持其他类似于STOMP的协议。其中包括org.springframework.messaging.simp包中的所有类。
至于URL路径参数,在WebSocket级别上,Spring没有提供任何东西,因为它主要是一个传输层。大部分有趣的事情发生在子协议级别。例如,对于STOMP,支持基于目标头的MessageMapping以及@DestinationVariable,它类似于在Spring MVC中使用@PathVariable,但基于目标头而不是URL。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接