spring - 在 Spring Websockets 上构建自定义 API

标签 spring spring-websocket

我必须通过 Websockets 实现自定义 API,这需要:

  • 自定义类 WAMP 子协议(protocol)
  • 套接字 URI 中的路径参数

  • 所以我有以下问题:
  • 是否有任何关于在 Spring 中实现自定义子协议(protocol)的文档或指南?协议(protocol)要求必须在 Sec-Websocket-Protocol 字段中指定确切的版本。可以在服务器端读取此字段的位置?
  • 将路径参数传递到消息处理程序的正确方法是什么?我可以在处理程序注册中使用 Ant 模式
        @Override 
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(customHandler(), "/api/custom/{clientId}");
        }
    

    但这些似乎在 TextWebSocketHandler 上不可用。我现在通过以下方式扩展默认的 HttpSessionHandshakeInterceptor 解决了这个问题:
    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);
        }
    }
    

    然后在 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);
        }
    
    }
    

    但在我看来,这种方法有点笨拙。有没有更合适的方法来解决这个问题?

  • 谢谢。

    最佳答案

    我能给出的最好建议是遵循内置的子协议(protocol)支持示例——从 SubProtocolWebSocketHandler 开始。和 SubProtocolHandler是它委托(delegate)包含StompSubProtocolHandler执行。 SubProtocolWebSocketHandler进一步连接到“clientInbound”和“clientOutbound” channel ,然后用于形成处理流以及提供线程边界。

    STOMP的处理流程有描述http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-message-flow这包括将消息委托(delegate)给带注释的 Controller 和/或消息代理,后者也可以将消息发送回下游给客户端。

    本质上是 StompSubProtocolHandler转换为 WebSocketMessage和一个 Spring Message具有特定于协议(protocol)的内容。因此,来自客户端入站 channel 的消息的 Controller 、消息代理或任何其他消费者都与 WebSocket 传输层分离并且不知道。围绕此类子协议(protocol)消息的构建、发送和处理而构建的许多设施旨在潜在地用于支持其他类似 STOMP 的协议(protocol)。这包括 org.springframework.messaging.simp 中的所有类包裹。

    至于 URL 路径参数,Spring 没有在 WebSocket 级别提供任何东西,这主要是一个传输层。大多数有趣的事情发生在子协议(protocol)级别。例如对于 STOMP 一个 MessageMapping支持基于目标 header 以及 @DestinationVariable这相当于使用 @PathVariable在 Spring MVC 中,但基于目标 header ,而不是 URL。

    关于spring - 在 Spring Websockets 上构建自定义 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35468770/

    相关文章:

    java - Spring Boot 请求头返回空值

    spring-websocket - Spring websocket 和群组消息

    java - 适用于多个主题的 Spring WebSockets

    java - 使用 JPA 从 child 获取 parent

    java - 如何扩展 afterPropertiesSet() 方法

    java - 如何为用户的 Activity 设置计时器?

    Spring Websocket - 如何检测客户端断开连接

    java - 如何在Spring mvc登录中更改登录成功Url

    spring-security - 如何防止Spring生成默认的simpSessionId?

    java - Spring WebSocket - Controller 发送消息后丢失