导读:本期聚焦于樱由罗创作的《Spring Boot 整合 Spring Cloud Gateway 实现微服务网关怎么做?》,敬请观看详情。微服务拆分之后,外部请求到底该从哪个入口进来?直接把各个服务暴露给前端显然不安全,也难以统一管理鉴权和限流。网关就是解决这个问题的核心组件,而 Spring Cloud Gateway 作为 Spring 官方推出的网关方案,基于 WebFlux 响应式模型构建,性能表现出色,且与 Spring Boot 无缝集成。本文将手把手演示如何搭建网关服务,从依赖引入、路由断言配置,到过滤器定制、跨域处理,再到与注册中心配合实现动态服务转发,最后补充常见的坑点排查方法,帮助你快速在生产环境落地一套可用的 API 网关。

当系统从一个单体应用拆分成多个微服务之后,最先撞上的问题往往不是服务之间怎么通信,而是外部请求该从哪里进来。如果让前端直接调用各个微服务的地址,不仅要处理一堆跨域问题,还等于把内部服务的细节全部暴露在外,安全性和可维护性都很差。网关的作用就是在请求与服务之间加一道统一入口,负责路由转发、鉴权、限流和日志记录。Spring Cloud Gateway 是 Spring 官方推出的网关实现,底层基于 Spring WebFlux 和 Project Reactor,性能比传统的 Zuul 1.x 好不少,与 Spring Boot 的整合也几乎是开箱即用。

Spring Boot 整合 Spring Cloud Gateway 实现微服务网关怎么做?

一、搭建网关工程并引入依赖

先创建一个独立的模块,专门作为网关服务。有一点必须提前强调:Spring Cloud Gateway 是基于 WebFlux 构建的,它依赖 Reactor Netty 作为底层服务器,因此工程中不能再引入 spring-boot-starter-web。两者共存时启动会直接报错,提示无法将 DispatcherServlet 与 WebFlux 混用,这是新手最常踩的坑。

在父工程确定好 Spring Boot 与 Spring Cloud 的版本对应关系后,网关模块只需要引入以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
&ltlt;dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

第二个依赖不是必须的,只有当你的服务注册到 Eureka、Nacos 等注册中心,希望通过服务名转发请求时才需要。如果暂时没有注册中心,也可以直接在路由里写死目标服务的 IP 和端口,先跑通流程。

版本对应关系建议查看 Spring Cloud 官方的 Release Train 说明,比如 Spring Boot 2.7.x 对应 Spring Cloud 2021.0.x。版本不匹配会出现各种奇怪的 Bean 注入失败问题,排查起来非常耗时,务必在项目初期就锁定好版本。

二、配置路由与断言规则

Spring Cloud Gateway 的核心概念有三个:Route(路由)是转发的完整规则,Predicate(断言)判断请求是否匹配该路由,Filter(过滤器)则在转发前后对请求和响应做加工。下面通过配置文件方式定义几条典型的路由规则:

server:
  port: 9000

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: http://localhost:8081
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
        - id: order-service-route
          uri: http://localhost:8082
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

上面配置的含义是:所有以 /api/user 开头的请求会被转发到 8081 端口的用户服务,StripPrefix=1 表示转发前去掉路径的第一级前缀,也就是把 /api/user/login 改写成 /user/login 再发给下游。如果不做这层剥离,下游服务就必须也带着 /api/user 前缀编写 Controller,路径会变得冗余。

断言的类型很丰富,除了 Path 之外,常用的还有 Method(限定 GET、POST 等)、Header(判断请求头)、Query(判断查询参数)、Before/After(限定时间窗口)。多个断言可以叠加,取交集生效。例如只允许携带 token 请求头的请求走某条路由:

predicates:
  - Path=/api/admin/**
  - Header=token, \d+

如果配置文件写起来太啰嗦,也可以用 Java 配置类的方式声明路由,适合规则需要动态计算的场景:

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("user-service-route", r -> r
                        .path("/api/user/**")
                        .filters(f -> f.stripPrefix(1))
                        .uri("http://localhost:8081"))
                .build();
    }
}

三、结合注册中心实现动态转发

写死 IP 和端口只能用于本地调试,生产环境必须接入注册中心。接入之后,路由的 uri 只需要写成 lb://服务名,网关会自动从注册中心拉取服务实例列表,并在客户端做负载均衡:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/user/**

lb:// 前缀表示 LoadBalancer 协议,网关转发前会根据服务名解析出实际地址。开启 discovery.locator 之后,甚至不需要手动配置路由,直接用 http://网关地址/服务名/接口路径 就能访问,不过这种方式把服务名暴露在 URL 中,实际项目中一般关闭它,改用显式路由规则。

需要注意,从 Spring Cloud 2020 版本开始 Ribbon 已经被移除,负载均衡由 Spring Cloud LoadBalancer 接管,依赖中要引入 spring-cloud-starter-loadbalancer,否则启动时会报一个找不到 ReactiveLoadBalancerClientFilter 依赖的警告,请求也无法正常转发。

四、自定义过滤器处理鉴权与日志

网关最常见的业务需求是统一鉴权。实现方式是编写全局过滤器,实现 GlobalFilterOrdered 接口,在请求转发前校验 Token:

@Component
public class AuthFilter implements GlobalFilter, Ordered {

    private static final List<String> WHITE_LIST = List.of("/api/user/login", "/api/user/register");

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        // 白名单直接放行
        if (WHITE_LIST.contains(path)) {
            return chain.filter(exchange);
        }
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (token == null || token.isEmpty()) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 校验通过后可以解析用户信息,塞进请求头传给下游
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("X-User-Id", parseUserId(token))
                .build();
        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

getOrder 返回值越小,过滤器优先级越高,鉴权过滤器应该设置得比较靠前,避免未认证的请求先经过记录日志之类的过滤器。校验通过后通过 mutate 修改请求,把用户 ID 写入自定义请求头,下游服务直接从请求头取用户身份,不需要再解析一次 Token。

跨域问题也建议统一在网关处理,不要让下游服务各自配置,否则容易出现重复的 CORS 头导致浏览器报错:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true

五、常见问题排查

整合过程中有几个高频报错值得记录。第一是启动报 Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway,原因就是前面说的引入了 web 依赖,检查依赖树用 mvn dependency:tree 找到传递引入的 starter-web 并排除即可。

第二是请求返回 503,通常是配置了 lb:// 但目标服务没有注册到注册中心,或者缺少 loadbalancer 依赖。可以在注册中心控制台确认服务是否在线。第三是返回 404,多半是 StripPrefix 的层级和下游接口路径对不上,可以临时开启日志观察实际转发的路径:

logging:
  level:
    org.springframework.cloud.gateway: debug
    reactor.netty: debug

把网关日志调成 debug 级别后,控制台会打印完整的路由匹配过程和最终转发地址,定位路径问题非常高效。掌握这些之后,一套具备路由转发、负载均衡和统一鉴权能力的网关服务就可以稳定支撑业务流量了,后续还可以在此基础上叠加 Sentinel 限流、灰度发布等高级能力。

Spring Boot GatewaySpring Cloud Gateway网关路由修改时间:2026-09-11 07:36:34

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260911/54549.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。