Обрабатывать один и тот же URL с помощью Spring MVC RequestMappingHandlerMapping и Spring Websocket ServletWebSocketHandlerRegistry
Что я хочу иметь:
- Клиент отправляет
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? Любые другие конфигурации, чтобы сделать то, что я описал первым?
Ответы
Ответ 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
для определения правильного обработчика для выполнения запроса.