使用Spring MVC RequestMappingHandlerMapping和Spring Websocket的ServletWebSocketHandlerRegistry处理相同的URL

2022-09-04 03:09:28

我想要什么:

  • 客户端发送(不带) - 此请求应由GET / HTTP/1.1Connection: upgradeRequestMappingHandlerMapping
  • 客户端随 GET 请求一起发送 - 此请求应由Connection: upgradeServletWebSocketHandlerRegistry

我的 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客户端(浏览器)时,它会响应为是否可以以某种方式将此错误页面替换为回退到我的MVC映射?是否有任何其他配置可以进行我首先描述的内容?Can "Upgrade" only to "WebSocket".


答案 1

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

当优先于 时,对于对它们都可以处理的终结点的请求(如果只考虑 URL),会将请求分派给方法,而不是 WebSocket 处理程序。为了解决这个问题,限制方法只为没有标头的请求提供服务:RequestMappingHandlerMappingWebSocketHandlerMappingDispatcherServlet@RequestMapping@RequestMappingConnection:Upgrade

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

这样,当搜索该公共终结点的处理程序时,它将考虑标头是否存在,以确定满足请求的正确处理程序。DispatcherServletConnection:Upgrade


答案 2

推荐