一、什么是 Spring Cloud Gateway?
Spring Cloud Gateway 是 Spring 生态专为微服务架构设计的 API 网关,基于 Netty 实现非阻塞响应式编程,核心功能包括:
- 路由转发:将客户端请求按规则转发到对应微服务
- 过滤器链:请求转发前后的增强处理(如认证、日志、限流)
- 负载均衡:集成 Spring Cloud LoadBalancer 实现服务实例动态路由
- 断言匹配:通过多种规则精确匹配请求
相比传统网关(如 Zuul),Gateway 具有更高的性能和更丰富的功能,是微服务架构的"流量入口"。
二、路由的核心组成
一个完整的 Gateway 路由由四部分构成:
| 要素 | 说明 |
|---|---|
| ID | 路由唯一标识(不可重复) |
| URI | 目标服务地址(支持 lb://服务名 或 http://ip:port) |
| Predicates | 路由断言(匹配请求的规则,多断言需同时满足) |
| Filters | 过滤器(请求转发前后的处理逻辑) |
三、路由配置方式(环境搭建)
1. 引入依赖
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>2. 配置文件方式(推荐)
通过 application.yml 配置,支持动态刷新:
server:
port: 8080 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
# 用户服务路由
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userService # 路由的目标地址 lb就是LoadBalance负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
filters:
- StripPrefix=1 # 去掉路径中第一个前缀(/api)
- AddRequestHeader=X-Service, user # 添加请求头
# 订单服务路由
- id: order-service-route
uri: http://localhost:8082 # 直接转发到指定地址
predicates:
- Path=/orders/**
- After=2025-10-01T00:00:00+08:00[Asia/Shanghai] # 时间断言3. 代码方式配置
通过 RouteLocatorBuilder 编程式定义路由:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 产品服务路由
.route("product-service-route", r -> r
.path("/api/products/**") // 路径断言
.filters(f -> f.stripPrefix(1)) // 过滤器
.uri("lb://product-service")) // 目标服务
.build();
}
}四、路由断言详解
断言(Predicate)是请求的"匹配规则",Gateway 内置多种断言工厂,支持组合使用(需同时满足)。
| 断言类型 | 示例 | 说明 |
|---|---|---|
| Path | Path=/api/**,/v1/** | 匹配请求路径(支持多路径和通配符 */**) |
| Method | Method=GET,POST | 匹配 HTTP 方法(GET/POST/PUT/DELETE 等) |
| Header | Header=X-Request-Id, \d+ | 匹配请求头(值支持正则表达式) |
| Query | Query=name, zhangsan | 匹配请求参数(如 ?name=zhangsan) |
| Host | Host=**.example.com | 匹配请求主机名(如 api.example.com) |
| Cookie | Cookie=sessionId, ^[a-z0-9]+$ | 匹配 Cookie 值(支持正则) |
| After | After=2025-10-28T12:00:00+08:00[Asia/Shanghai] | 匹配指定时间之后的请求 |
| Before | Before=2025-12-31T23:59:59+08:00[Asia/Shanghai] | 匹配指定时间之前的请求 |
| Between | Between=2025-10-01T00:00:00+08:00[Asia/Shanghai], 2025-12-31T23:59:59+08:00[Asia/Shanghai] | 匹配时间区间内的请求 |
组合断言示例:
predicates:
- Path=/api/pay/**
- Method=POST
- Header=Content-Type, application/json
- Query=source, app # 要求包含 source=app 参数五、过滤器详解
过滤器用于请求转发的增强处理,按生效范围分为:
- 局部过滤器:仅对绑定的路由生效
- 全局过滤器:对所有路由生效
1. 常用内置过滤器
| 过滤器 | 示例 | 说明 |
|---|---|---|
| StripPrefix | StripPrefix=2 | 去掉路径前 N 级前缀(如 /api/v1/users→/users) |
| PrefixPath | PrefixPath=/api | 给路径添加前缀(如 /users→/api/users) |
| AddRequestHeader | AddRequestHeader=X-Env, prod | 添加请求头 |
| AddResponseHeader | AddResponseHeader=X-Gateway, scg | 添加响应头 |
| SetPath | SetPath=/new/{segment} | 重写路径(使用占位符) |
| RequestRateLimiter | 见实战案例 | 基于 Redis 令牌桶的限流 |
| CircuitBreaker | 见实战案例 | 熔断降级(需结合 Resilience4j) |
全局内置过滤器(对所有路由生效):
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Powered-By, SpringCloudGateway
- Logging=INFO # 日志过滤器2. 自定义局部过滤器(继承 AbstractGatewayFilterFactory)
规范:类名必须以 GatewayFilterFactory 结尾(Spring 自动扫描要求),否则无法在配置文件中引用。
案例:接口版本校验过滤器
需求:通过请求头 X-API-Version 控制访问,仅允许指定版本的请求通过。
步骤 1:实现过滤器
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
// 类名必须以 GatewayFilterFactory 结尾,否则配置文件无法识别
@Component
public class ApiVersionGatewayFilterFactory extends AbstractGatewayFilterFactory<ApiVersionGatewayFilterFactory.Config> {
// 配置类:存储过滤器参数(允许的版本号)
public static class Config {
private String allowedVersion;
// getter 和 setter
public String getAllowedVersion() { return allowedVersion; }
public void setAllowedVersion(String allowedVersion) { this.allowedVersion = allowedVersion; }
}
// 构造器:指定配置类类型
public ApiVersionGatewayFilterFactory() {
super(Config.class);
}
// 定义配置参数的顺序(与 Config 属性对应)
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("allowedVersion");
}
// 核心过滤逻辑
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 1. 获取请求头中的版本号
String requestVersion = exchange.getRequest().getHeaders().getFirst("X-API-Version");
// 2. 校验版本
if (config.getAllowedVersion().equals(requestVersion)) {
// 版本匹配,继续执行后续过滤器
return chain.filter(exchange);
} else {
// 版本不匹配,返回 403 禁止访问
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
};
}
}步骤 2:绑定到路由
在配置文件中通过类名前缀引用(去掉 GatewayFilterFactory 后缀):
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
# 引用自定义过滤器(使用前缀 ApiVersion)
- name: ApiVersion
args:
allowedVersion: v2 # 允许 v2 版本访问3. 自定义全局过滤器(实现 GlobalFilter)
全局过滤器对所有路由生效,需实现 GlobalFilter 和 Ordered 接口,并通过 @Component 注入容器。
案例:Token 认证全局过滤器
需求:所有请求必须携带有效的 Token(请求头 Authorization),否则拒绝访问。
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class TokenAuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, org.springframework.cloud.gateway.filter.GatewayFilterChain chain) {
// 1. 获取请求头中的 Token
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// 2. 校验 Token(实际项目需调用认证服务)
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 3. Token 有效,继续执行
return chain.filter(exchange);
}
/**
* 执行顺序:数值越小优先级越高
* 此处设置在响应写入前执行(NettyWriteResponseFilter.ORDER = -1)
*/
@Override
public int getOrder() {
return NettyWriteResponseFilter.ORDER - 1;
}
}六、路由优先级与动态配置
1. 路由优先级
当多个路由的断言同时匹配请求时,配置顺序决定优先级(先配置的路由优先匹配)。建议:
- 精确匹配的路由放在前面
- 模糊匹配的路由放在后面
routes:
# 精确匹配优先
- id: user-detail-route
uri: lb://user-service
predicates:
- Path=/api/users/{id} # 匹配单个用户查询
# 模糊匹配在后
- id: user-list-route
uri: lb://user-service
predicates:
- Path=/api/users/** # 匹配所有用户相关请求2. 动态路由配置
通过配置中心(如 Nacos、Apollo)实现路由动态更新,无需重启网关:
- 在配置中心创建
gateway-routes.yml存储路由配置 - 网关服务引入配置中心依赖并配置地址
- 配置中心推送变更后,网关自动刷新路由
七、实战案例:完整配置
spring:
application:
name: api-gateway
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Gateway, SpringCloudGateway
# 全局限流过滤器
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 令牌生成速率(每秒10个)
redis-rate-limiter.burstCapacity: 20 # 令牌桶容量
key-resolver: "#{@ipKeyResolver}" # 按IP限流
routes:
# 用户服务路由(绑定版本过滤器)
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/v1/users/**
- Method=GET,POST
filters:
- StripPrefix=2 # 去掉 /api/v1 前缀
- name: ApiVersion
args:
allowedVersion: v1
# 订单服务路由(熔断处理)
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/v1/orders/**
- After=2025-01-01T00:00:00+08:00[Asia/Shanghai]
filters:
- StripPrefix=2
- name: CircuitBreaker
args:
name: orderServiceCircuitBreaker
fallbackUri: forward:/fallback/orders # 熔断降级地址配套限流 KeyResolver:
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class RateLimitConfig {
// 按客户端IP限流
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
}八、调试技巧
开启 Debug 日志:
logging: level: org.springframework.cloud.gateway: debug # 打印路由匹配和过滤器执行日志使用 Actuator 端点:
management: endpoints: web: exposure: include: gateway, routes # 暴露网关监控端点访问
http://localhost:8080/actuator/gateway/routes可查看所有路由配置。
九、总结
通过本文,你已掌握:
- 路由的核心组成与两种配置方式(文件/代码)
- 断言规则的组合使用(路径、方法、时间等)
- 内置过滤器的常用场景(路径处理、头信息添加等)
自定义过滤器的实现:
- 局部过滤器:继承
AbstractGatewayFilterFactory,类名以GatewayFilterFactory结尾 - 全局过滤器:实现
GlobalFilter和Ordered接口
- 局部过滤器:继承
- 路由优先级与动态配置技巧
合理设计路由和过滤器,能让 Gateway 成为微服务架构的"智能入口",实现请求的高效转发与安全管控。