【问题标题】:Handle the same URL with Spring MVC RequestMappingHandlerMapping and Spring Websocket's ServletWebSocketHandlerRegistry使用 Spring MVC RequestMappingHandlerMapping 和 Spring Websocket 的 ServletWebSocketHandlerRegistry 处理相同的 URL
【发布时间】:2016-07-14 14:02:14
【问题描述】:

我想要什么:

  • 客户端发送GET / HTTP/1.1(没有Connection: upgrade) - 这个请求应该由RequestMappingHandlerMapping处理
  • 客户端发送Connection: upgrade连同GET请求 - 这个请求应该由ServletWebSocketHandlerRegistry处理

我的 Java 配置:

@Configuration
@EnableWebSocket
public class WebsocketConfiguration extends WebMvcConfigurationSupport 
                                    implements WebSocketConfigurer {
    @Bean
    WebsocketComponent wsHandler() {
        return new WebsocketComponent();
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(wsHandler(), "/").setAllowedOrigins("*");
    }
}

我的 webmvc 控制器:

@Controller
public class Status {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String status() {
        return "OK";
    }
}

问题是 - 当 MVC 控制器优先时,它总是以 HTTP 200 响应,WebSocket 处理程序从未到达。当 WebSocket 处理程序具有优先权时 - 它适用于 WebSocket 客户端,但是当我尝试 http 客户端(浏览器)时,它会以 Can "Upgrade" only to "WebSocket". 响应 是否可以用回退到我的 MVC 映射来以某种方式替换此错误页面?还有其他配置可以实现我首先描述的内容吗?

【问题讨论】:

  • 确定 Spring MVC 的请求映射的优先级低于 WebSocket 映射吗?例如,您可以在ws://localhost:8080/status 上打开 Web 套接字连接吗?
  • @AliDehghani 当然,websocket 连接有效,普通 http 连接无效:00:30:20 错误握手失败,由于升级标头无效:null
  • 显然,您的WebSocketHandlerMapping 优先于您的RequestMappingHandlerMapping。通常情况相反,请发布更多关于您的配置的信息
  • 出于好奇:你为什么要在同一个 url 上?为什么不给 websockets 一些不同的 uri?
  • @AleksandrM 1) 这就是我的遗留应用程序的工作方式,我想使用 spring-websockets 而不是手写的 websocket 服务器并与客户端保持兼容 2) 最好有更多描述性的消息和说明比神秘的can upgrade only to websocket

标签: java spring spring-mvc spring-websocket


【解决方案1】:

问题是 - 当 MVC 控制器优先时,它总是 以 HTTP 200 响应,WebSocket 处理程序从未到达

RequestMappingHandlerMapping 优先于WebSocketHandlerMapping 时,对于向他们双方都可以处理的端点的请求(如果您只考虑URL),DispatcherServlet 会将请求分派给@RequestMapping 方法,而不是WebSocket 处理程序。为了解决这个问题,限制@RequestMapping方法只服务没有Connection:Upgrade头的请求:

@Controller
public class Status {
    @RequestMapping(value = "/", method = GET, headers = "Connection!=Upgrade")
    public String status() {
        return "OK";
    }
}

这样,当DispatcherServlet 搜索该公共端点的处理程序时,它会考虑是否存在Connection:Upgrade 标头来确定满足请求的正确处理程序。

【讨论】:

  • 很好的解释!就我而言,我不得不加倍测试:headers = {"Connection!=upgrade", "Connection!=Upgrade" }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 2012-02-18
  • 2015-02-11
  • 2015-10-16
相关资源
最近更新 更多