【日常小问】Spring Cloud Gateway 5.x 跨域和路由配置踩坑实录

一、问题出现

最近把一个 Spring Boot 3.x 的项目升级到 Spring Boot 4.0.6 + Spring Cloud 2025.1.x(对应 Gateway 5.x),顺便引入 Spring Cloud Gateway 做统一的 API 网关。本以为只是个常规的架构调整,结果折腾了一整个下午。

前端项目跑在 localhost:3000,网关跑在 8080,按理说配个路由和跨域就完事了。结果启动后遇到三个连环报错:

第一关:Gateway 启动就挂

复制代码
ClassNotFoundException: org.springframework.boot.web.context.WebServerInitializedEvent

第二关:路由全 404

复制代码
No RouteDefinition found for [Exchange: POST http://localhost:8080/api/auth/login/password]

第三关:跨域重复

复制代码
Access-Control-Allow-Origin header contains multiple values 'http://localhost:3000, http://localhost:3000'

这三个问题其实是三个独立的原因,只是凑在一起爆发了。

二、问题原因

2.1 依赖坐标改了

第一个问题最直接。旧版 Gateway 的依赖是:

复制代码
<!-- 旧版(Spring Cloud 2024.x 及之前) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

到了 5.x,这个 artifact 被重命名了:

复制代码
<!-- 新版(Spring Cloud 2025.x / Gateway 5.x) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>
</dependency>

直接用旧坐标会导致类找不到 WebServerInitializedEvent------因为旧的 spring-cloud-starter-gateway 依赖了 spring-cloud-gateway-server,而后者在 5.x 中被拆分为 spring-cloud-gateway-server-webflux,包结构和类名都有变化。

2.2 配置前缀改了------这是最坑的

这是今天最大的坑。Gateway 5.x 把配置前缀改了:

版本 配置前缀
Gateway 4.x(旧) spring.cloud.gateway
Gateway 5.x(新) spring.cloud.gateway.server.webflux

看源码的 GatewayProperties.java 第 45 行:

复制代码
public static final String PREFIX = "spring.cloud.gateway.server.webflux";

也就是说,路由配置要从:

复制代码
# ❌ 旧写法------Gateway 5.x 不认
spring:
  cloud:
    gateway:
      routes:
        - id: auth-service
          uri: http://localhost:8001

改成:

复制代码
# ✅ 新写法
spring:
  cloud:
    gateway:
      server:
        webflux:
          routes:
            - id: auth-service
              uri: http://localhost:8001

不只是路由,globalcors 的配置也一样:

复制代码
# ✅ globalcors 也在新前缀下面
spring:
  cloud:
    gateway:
      server:
        webflux:
          globalcors:
            cors-configurations:
              '[/**]':
                allowedOriginPatterns: "*"

我当时就纳闷,明明配置看起来没问题,为什么路由就是加载不到?看启动日志只看到 No RouteDefinition found,没有任何报错。翻源码才找到这个前缀变化。

2.3 跨域重复------Gateway 和下游服务同时在设

第三个问题最有意思。Gateway 的 RoutePredicateHandlerMapping 在匹配路由后,会自动根据 globalcors 配置往响应头里写 Access-Control-Allow-Origin。

但我的下游服务(auth-service、user-service 等)也各自配了 Spring Security 的 CORS:

复制代码
// 每个服务的 SecurityConfig 都有这个
.cors(cors -> cors.configurationSource(corsConfigurationSource()))

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    // ... 设置了 allowedOrigins、allowedMethods 等
}

结果就是:浏览器发一个请求,Gateway 写一次 CORS 头,下游服务又写一次 。最终响应头里出现两个一模一样的 Access-Control-Allow-Origin: http://localhost:3000,浏览器直接拒绝。

三、解决问题

相关推荐
驭渊的小故事34 分钟前
MyBatis XML 开发实战:从配置到 CRUD 全解析
xml·java·mybatis
哦虎!5 小时前
【JavaEE】网络初识
java
for_ever_love__6 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
我是人✓7 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
欣栀♡7 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室7 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项7 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs
Wang's Blog7 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务提供者
java·dubbo·交友
秋饼8 小时前
Spring AI 2.0 结构化输出企业级实战:从 BeanOutputConverter 源码到生产级解析容错
java·ai·技术分享·后端开发
摇滚侠8 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记