You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud微服务中WebSocket触发ClassCastException的问题解决问询

解决方案:Spring Cloud Gateway 与 WebSocket 微服务兼容配置

问题核心

Spring Cloud Gateway 强制要求Reactive 运行环境(web-application-type: reactive),但传统的 spring-boot-starter-websocket 依赖 spring-boot-starter-web(MVC 环境),导致 Reactive 与非 Reactive 组件冲突,引发类型转换异常和握手失败。


方案一:将微服务改为 Reactive WebSocket 实现(推荐)

放弃传统 MVC 风格的 WebSocket,改用 Spring WebFlux 提供的 Reactive WebSocket 支持,彻底消除环境冲突。

1. 调整依赖

移除 spring-boot-starter-websocket,添加 Reactive Web 依赖:

<!-- 移除旧依赖 -->
<!-- <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency> -->

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

2. 编写 Reactive WebSocket 处理器

实现 WebSocketHandler 处理消息逻辑:

import org.springframework.stereotype.Component;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Mono;

@Component
public class RequestChatWebSocketHandler implements WebSocketHandler {

    @Override
    public Mono<Void> handle(WebSocketSession session) {
        // 从路径参数获取 userId 和 requestId
        String userId = session.getHandshakeInfo().getPathVariables().get("userId");
        String requestId = session.getHandshakeInfo().getPathVariables().get("requestId");

        // 消息处理逻辑:接收客户端消息并返回响应
        return session.send(
                session.receive()
                        .map(msg -> String.format("【请求%s】用户%s发送消息:%s", requestId, userId, msg.getPayloadAsText()))
                        .map(session::textMessage)
        );
    }
}

3. 配置 WebSocket 路由

通过路由函数映射请求路径:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;

@Configuration
public class WebSocketConfig {

    @Bean
    public RouterFunction<?> webSocketRouter(RequestChatWebSocketHandler handler) {
        return RouterFunctions.route(
                RequestPredicates.path("/api/v1/request_chat/{userId}/{requestId}"),
                handler
        );
    }

    @Bean
    public WebSocketHandlerAdapter webSocketHandlerAdapter() {
        return new WebSocketHandlerAdapter();
    }
}

4. 微服务配置

保持 Reactive 环境配置:

spring:
  application:
    name: requests-service
  web:
    application-type: reactive
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

方案二:网关配置 WebSocket 转发规则

确保网关正确识别并转发 WebSocket 请求:

spring:
  application:
    name: gateway-service
  web:
    application-type: reactive
  cloud:
    gateway:
      routes:
        - id: requests-service-websocket
          uri: lb://requests-service # 基于 Eureka 服务名负载均衡
          predicates:
            - Path=/requests-service/api/v1/request_chat/**
          filters:
            - StripPrefix=1 # 移除路径前缀 `requests-service`,匹配微服务实际路径
          metadata:
            websocket: true # 标记为 WebSocket 路由
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

验证步骤

  1. 启动 Eureka Server
  2. 启动调整后的 WebSocket 微服务
  3. 启动 Spring Cloud Gateway
  4. 使用 WebSocket 客户端连接 ws://localhost:8080/requests-service/api/v1/request_chat/1/1,发送消息测试,确认无 500 错误和类型转换异常。

内容的提问来源于stack exchange,提问作者Sam Fisher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:37:29