GateWay断言
Spring Cloud Gateway 断言(Predicate)详解:精准匹配请求的核心机制
Spring Cloud Gateway 的断言(Predicate)是路由匹配的核心,它通过匹配 HTTP 请求的各种属性(如路径、方法、头信息、时间等),决定是否将请求转发到目标服务。Gateway 内置了多种断言工厂,满足不同场景的路由匹配需求。
断言的本质
断言(Predicate)本质是请求匹配规则,基于 Java 8 的Predicate函数式接口实现。当请求到达网关时,Gateway 会依次执行路由中定义的断言:
- 若所有断言均返回
true,则请求匹配该路由,执行转发; - 若任一断言返回
false,则跳过该路由,继续匹配其他路由。
断言的配置方式有两种:
- 简短配置:
- 断言名=参数1,参数2(适合简单场景); - 全面配置:通过
name和args显式指定参数(适合复杂场景)。
示例(Cookie 断言的两种配置):
# 简短配置
predicates:
- Cookie=userName, zhangsan
# 全面配置
predicates:
- name: Cookie
args:
name: userName
regexp: zhangsan
常用断言详解
Gateway 内置了 10 余种断言工厂,以下是最常用的几种:
1. 时间类断言:基于请求时间匹配
(1)After 断言
匹配在指定时间之后的请求。
predicates:
# 匹配2024-01-01 00:00:00之后的请求(时区Asia/Shanghai)
- After=2024-01-01T00:00:00+08:00[Asia/Shanghai]
- 格式:
After=时间字符串(时间格式为yyyy-MM-ddTHH:mm:ss±HH:MM[时区])。
(2)Before 断言
匹配在指定时间之前的请求。
predicates:
# 匹配2024-12-31 23:59:59之前的请求
- Before=2024-12-31T23:59:59+08:00[Asia/Shanghai]
(3)Between 断言
匹配在两个时间之间的请求。
predicates:
# 匹配2024-01-01到2024-12-31之间的请求
- Between=2024-01-01T00:00:00+08:00[Asia/Shanghai], 2024-12-31T23:59:59+08:00[Asia/Shanghai]
2. 请求属性类断言:基于 HTTP 请求信息匹配
(1)Path 断言(最常用)
匹配请求路径(支持通配符)。
predicates:
# 匹配/dept/开头的路径(如/dept/get/1、/dept/list)
- Path=/dept/**
# 多路径匹配(/user/或/order/开头)
- Path=/user/**,/order/**
- 通配符规则:
*匹配单层路径,**匹配多层路径(如/dept/*匹配/dept/1,但不匹配/dept/1/info)。
(2)Method 断言
匹配指定的 HTTP 方法(如 GET、POST)。
predicates:
# 仅允许GET和POST请求
- Method=GET,POST
(3)Query 断言
匹配请求参数(支持正则表达式)。
predicates:
# 匹配包含参数id,且值为数字的请求(如?id=123)
- Query=id, \d+
# 仅匹配包含参数name的请求(不限制值)
- Query=name
(4)Header 断言
匹配请求头(支持正则表达式)。
predicates:
# 匹配包含X-Request-Id头,且值为数字的请求
- Header=X-Request-Id, \d+
(5)Cookie 断言
匹配 Cookie(支持正则表达式)。
predicates:
# 匹配包含userName=zhangsan的Cookie
- Cookie=userName, zhangsan
3. 网络类断言:基于请求来源匹配
(1)RemoteAddr 断言
匹配请求的客户端 IP 地址。
predicates:
# 匹配IP在192.168.1.0/24网段的请求(如192.168.1.100)
- RemoteAddr=192.168.1.1/24
- 格式:支持 IP 地址或 CIDR 网段(如
10.0.0.0/8)。
(2)Host 断言
匹配请求的 Host 域名(支持 Ant 风格通配符)。
predicates:
# 匹配*.example.com或*.demo.org的域名(如api.example.com、www.demo.org)
- Host=**.example.com,**.demo.org
4. 路由权重类断言:Weight 断言
用于实现权重路由,按比例将请求分发到不同目标服务(灰度发布常用)。
routes:
# 80%的请求路由到weighthigh.org
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8 # group1为分组名,8为权重
# 20%的请求路由到weightlow.org
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2 # 同一分组内权重总和为10(8+2)
- 同一分组(如
group1)的权重总和为比例分母,单个路由的权重为分子。
断言的组合使用
多个断言可以组合使用,所有断言必须同时满足才会匹配路由。
示例:仅允许工作时间(9:00-18:00)的 GET 请求访问/api/**路径:
routes:
- id: combined_route
uri: lb://api-service
predicates:
- Path=/api/** # 路径匹配
- Method=GET # 方法匹配
- Between=2024-01-01T09:00:00+08:00[Asia/Shanghai], 2024-12-31T18:00:00+08:00[Asia/Shanghai] # 时间匹配
自定义断言(扩展)
若内置断言无法满足需求,可自定义断言工厂,步骤如下:
- 创建配置类:定义断言所需参数;
- 实现
RoutePredicateFactory:重写apply方法,编写匹配逻辑; - 注册为 Spring Bean:通过
@Component注解生效。
示例:自定义 “请求头包含版本号” 的断言:
// 1. 配置类(存储参数)
public static class Config {
private String version;
// getter和setter
}
// 2. 自定义断言工厂
public class VersionRoutePredicateFactory extends AbstractRoutePredicateFactory<VersionRoutePredicateFactory.Config> {
public VersionRoutePredicateFactory() {
super(Config.class);
}
public Predicate<ServerWebExchange> apply(Config config) {
// 匹配逻辑:请求头包含X-Version且值等于配置的version
return exchange -> {
String version = exchange.getRequest().getHeaders().getFirst("X-Version");
return version != null && version.equals(config.getVersion());
};
}
// 配置参数解析(指定参数名和顺序)
public List<String> shortcutFieldOrder() {
return Collections.singletonList("version");
}
}
使用自定义断言:
predicates:
- Version=v1 # 匹配X-Version=v1的请求
总结
Gateway 的断言是实现精准路由的核心,通过内置的时间、路径、方法、权重等断言,可满足大多数场景的路由匹配需求