You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

引入spring-web后Spring Reactive WebSocket无法启动(404)求助

问题分析与解决方案

这个问题我之前帮不少开发者排查过,核心是Spring Boot中Servlet栈和Reactive栈的自动配置优先级差异,以及两种WebSocket实现的机制区别,咱们一步步拆解:

首先明确:spring-web(Servlet栈)和spring-webflux(Reactive栈)本身不存在依赖冲突,但Spring Boot的自动配置会让两者共存时优先激活Servlet栈——这就是你遇到404的根源。

为什么会出现404?

当你同时引入spring-boot-starter-web(Tomcat Servlet栈)和spring-webflux时,Spring Boot会默认把Servlet栈作为应用的核心容器。而你配置的Reactive WebSocket端点是注册在WebFlux的路由系统中的,Servlet栈的Tomcat根本不会处理这些Reactive路由,自然就返回404了。

你尝试添加的TomcatRequestUpgradeStrategy是给Servlet栈下的常规WebSocket(基于Servlet规范的实现)用的,和Reactive WebSocket完全是两套机制,所以解决不了问题。

两种可行的解决方案

方案1:切换到Reactive栈(保留Reactive WebSocket)

如果你的新功能更偏向响应式,且现有代码可以兼容Reactive栈,建议直接移除spring-boot-starter-web,改用spring-boot-starter-webflux作为核心依赖:

<!-- 移除Servlet栈依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 添加Reactive栈依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

这样应用会默认使用Netty作为容器(也可以配置为Reactive版的Tomcat/Jetty/Undertow),WebFlux的路由(包括Reactive WebSocket端点)会被正常加载,就能和你之前运行的示例一样正常工作了。

方案2:保留Servlet栈,改用常规WebSocket

如果你的现有应用大量依赖Servlet栈的代码,不想切换到Reactive栈,那就要放弃Reactive WebSocket,改用Servlet规范的WebSocket实现:

  1. 可以直接用JSR-356的@ServerEndpoint注解定义WebSocket端点;
  2. 或者用Spring提供的WebSocketHandler结合WebSocketConfigurer来配置,这时候TomcatRequestUpgradeStrategy就能派上用场,用来处理Tomcat下的WebSocket升级请求。

举个简单的Spring WebSocket配置示例:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyWebSocketHandler(), "/ws")
                .setAllowedOrigins("*")
                .withSockJS(); // 可选,支持降级到SockJS适配低版本浏览器
    }
}

总结

  • 不是spring-web和spring-webflux的依赖冲突,而是Spring Boot自动配置的优先级导致Reactive端点在Servlet栈下不生效;
  • 选择哪种WebSocket实现,完全取决于你是否愿意切换到Reactive栈:想保留响应式特性就换WebFlux栈,想继续用Tomcat Servlet栈就改用常规WebSocket。

内容的提问来源于stack exchange,提问作者Venkatesh Laguduva

火山引擎 最新活动