跳到主要内容

网关请求断言

DeepSeek V3 中英对照 Gateway Request Predicates

Spring Cloud Gateway MVC 将路由匹配作为 Spring WebMvc.fn HandlerMapping 基础设施的一部分。Spring Cloud Gateway 重用了许多来自 WebMvc.fn 的 RequestPredicate 实现,并包含其他自定义的 RequestPredicate 实现。所有这些断言都基于 HTTP 请求的不同属性进行匹配。你可以使用 RequestPredicate.and()RequestPredicate.or() 方法将多个路由断言工厂组合在一起。

请求后断言

After 路由谓词工厂接受一个参数,即 datetime(这是一个 Java ZonedDateTime 类型)。该谓词匹配发生在指定日期时间之后的请求。以下示例配置了一个 after 路由谓词:

spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2023-10-01T00:00:00+08:00[Asia/Shanghai]
yaml
spring:
cloud:
gateway:
mvc:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
yaml
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.after;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsAfter() {
return route("after_route")
.route(after(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
.build();
}
}
java

该路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后发出的任何请求。

请求前置断言

Before 路由谓词工厂接受一个参数,即 datetime(这是一个 Java 的 ZonedDateTime)。该谓词匹配在指定 datetime 之前发生的请求。以下示例配置了一个 before 路由谓词:

spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2023-12-31T23:59:59Z
yaml

在这个示例中,所有在 2023 年 12 月 31 日 23:59:59 UTC 之前发生的请求都将被匹配。

spring:
cloud:
gateway:
mvc:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
yaml
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.before;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsBefore() {
return route("before_route")
.route(before(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
.build();
}
}
java

该路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之前发出的任何请求。

Between 请求谓词

Between 路由谓词工厂接受两个参数,datetime1datetime2,它们是 Java 的 ZonedDateTime 对象。这个谓词会匹配发生在 datetime1 之后且在 datetime2 之前的请求。datetime2 参数必须在 datetime1 之后。以下示例配置了一个 between 路由谓词:

spring:
cloud:
gateway:
mvc:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
yaml
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsBetween() {
return route("between_route")
.route(between(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]"), ZonedDateTime.parse("2017-01-21T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
.build();
}
}
java

该路由匹配任何在 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后且在 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前发出的请求。这对于维护窗口可能很有用。

Cookie 路由谓词工厂接受两个参数,分别是 cookie 的 name 和一个 regexp(即 Java 正则表达式)。该谓词用于匹配具有指定名称且其值符合正则表达式的 cookie。以下示例配置了一个 cookie 路由谓词工厂:

spring:
cloud:
gateway:
mvc:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
yaml
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
return route("cookie_route")
.route(cookie("chocolate", "ch.p"), http("https://example.org"))
.build();
}
}
java

此路由匹配具有名为 chocolate 的 cookie 的请求,且该 cookie 的值与 ch.p 正则表达式匹配。

头部请求谓词

Header 路由谓词工厂接受两个参数,header 和一个 regexp(这是一个 Java 正则表达式)。该谓词与具有给定名称且其值与正则表达式匹配的标头进行匹配。以下示例配置了一个标头路由谓词:

spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
yaml

在此示例中,Header 谓词将匹配任何带有 X-Request-Id 标头且其值为一个或多个数字的请求。

spring:
cloud:
gateway:
mvc:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
yaml
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.header;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
return route("cookie_route")
.route(header("X-Request-Id", "\\d+"), http("https://example.org"))
.build();
}
}
java

该路由在请求具有名为 X-Request-Id 的标头且其值匹配 \d+ 正则表达式时匹配(即,该标头的值为一个或多个数字)。

主机请求谓词

Host 路由谓词工厂接受一个参数:主机名 patterns 的列表。该模式是一个以 . 作为分隔符的 Ant 风格模式。此谓词匹配与模式匹配的 Host 头。以下示例配置了一个主机路由谓词:

spring:
cloud:
gateway:
mvc:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
yaml
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsHost() {
return route("host_route")
.route(host("**.somehost.org", "**.anotherhost.org"), http("https://example.org"))
.build();
}
}
java

URI 模板变量(例如 {sub}.myhost.org)同样受到支持。

此路由在请求的 Host 头值为 www.somehost.orgbeta.somehost.orgwww.anotherhost.org 时匹配。

该谓词提取 URI 模板变量(例如前面示例中定义的 sub)作为名称和值的映射,并将其放入 ServerRequest.attributes() 中,键由 MvcUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。然后,这些值可供 Gateway Handler Filter Functions 使用。

方法请求谓词

Method 请求断言接受一个 methods 参数,该参数是一个或多个 HTTP 方法的参数:用于匹配的 HTTP 方法。以下示例配置了一个方法路由断言:

spring:
cloud:
gateway:
mvc:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
yaml
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
return route("method_route")
.route(method(HttpMethod.GET, HttpMethod.POST), http("https://example.org"))
.build();
}
}
java

如果请求方法是 GETPOST,则此路由匹配。

GatewayRequestPredicates.methodRequestPredicates.methods 的一个简单别名。此外,RouterFunctions.Builder API 包含了一些便捷方法,这些方法将 methodpathRequestPredicates 结合在一起。

import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.methods;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
return route("method_route")
.GET("/mypath", http("https://example.org"))
.build();
}
}
java

如果请求方法是 GET 且路径为 /mypath,则此路由匹配。

路径请求谓词

Path 请求谓词接受两个参数:一个 Spring PathPattern 模式的列表。此请求谓词使用 RequestPredicates.path() 作为底层实现。以下示例配置了一个路径路由谓词:

spring:
cloud:
gateway:
mvc:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
yaml
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsPath() {
return route("path_route")
.route(path("/red/{segment}", "/blue/{segment}"), http("https://example.org"))
.build();
}
}
java

此路由匹配的请求路径可以是:/red/1/red/1//red/blue/blue/green

此谓词将 URI 模板变量(例如前面示例中定义的 segment)提取为名称和值的映射,并将其放入 ServerRequest.attributes() 中,键为 RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后,这些值可供 Gateway Handler Filter Functions 使用。

一个实用方法(称为 get)可用于更轻松地访问这些变量。以下示例展示了如何使用 get 方法:

Map<String, Object> uriVariables = MvcUtils.getUriTemplateVariables(request);

String segment = uriVariables.get("segment");
java

查询请求谓词

Query 路由断言工厂接受两个参数:一个必需的 param 和一个可选的 regexp(这是一个 Java 正则表达式)。以下示例配置了一个查询路由断言:

spring:
cloud:
gateway:
mvc:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
yaml
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
return route("query_route")
.route(query("green"), http("https://example.org"))
.build();
}
}
java

前面的路由会在请求包含 green 查询参数时匹配。

spring:
cloud:
gateway:
mvc:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.
yaml
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
return route("query_route")
.route(query("red", "gree."), http("https://example.org"))
.build();
}
}
java

前面的路由会在请求包含一个 red 查询参数且其值匹配正则表达式 gree. 时匹配,因此 greengreet 会匹配。

权重请求谓词

Weight 路由谓词工厂接受两个参数:groupweight(一个 int 类型)。权重是按组计算的。以下示例配置了一个权重路由谓词:

spring:
cloud:
gateway:
mvc:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
yaml
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsWeights() {
return route("weight_high")
.route(weight("group1", 8).and(path("/**")), http("https://weighthigh.org"))
.build().and(
route("weight_low")
.route(weight("group1", 2).and(path("/**")), http("https://weightlow.org"))
.build());
}
}
java

这条路由将把大约 80% 的流量转发到 weighthigh.org,大约 20% 的流量转发到 weightlow.org