网关请求谓词
Spring Cloud Gateway MVC 作为 Spring WebMvc.fn 的 HandlerMapping 基础设施的一部分来匹配路由。Spring Cloud Gateway 复用了许多 RequestPredicate 实现,并包含了其他自定义的 RequestPredicate 实现。所有这些谓词都匹配 HTTP 请求的不同属性。您可以通过 RequestPredicate.and() 和 RequestPredicate.or() 方法组合多个路由谓词工厂。
After 请求谓词
After 路由谓词工厂接受一个参数,即一个 datetime(一个 Java 的 ZonedDateTime 对象)。此谓词匹配发生在指定日期时间之后的请求。以下示例配置了一个 after 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
此路由匹配 2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之后发生的任何请求。
Before 请求谓词
Before 路由谓词工厂接受一个参数,即一个 datetime(一个 Java 的 ZonedDateTime 对象)。此谓词匹配发生在指定 datetime 之前的请求。以下示例配置了一个 before 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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()
.before(uri("https://example.org"))
.build();
}
}
此路由匹配 2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之前发生的任何请求。
Between 请求谓词
Between 路由谓词工厂接受两个参数,datetime1 和 datetime2,它们都是 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]
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
此路由匹配发生在 2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之后且在 2017 年 1 月 21 日 17:42 Mountain Time (Denver) 之前的任何请求。这对于维护时段很有用。
Cookie 请求谓词
Cookie 路由谓词工厂接受两个参数:cookie 的 name 和一个 regexp(一个 Java 正则表达式)。此谓词匹配具有给定名称且值匹配正则表达式的 cookie。以下示例配置了一个 cookie 路由谓词工厂
spring:
cloud:
gateway:
mvc:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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.cookie;
@Configuration
class RouteConfiguration {
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
return route("cookie_route")
.route(cookie("chocolate", "ch.p"), http())
.before(uri("https://example.org"))
.build();
}
}
此路由匹配具有名为 chocolate 且值匹配 ch.p 正则表达式的 cookie 的请求。
Header 请求谓词
Header 路由谓词工厂接受两个参数:header 名称和一个 regexp(一个 Java 正则表达式)。此谓词匹配具有给定名称且值匹配正则表达式的 header。以下示例配置了一个 header 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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> gatewayRouterFunctionsHeader() {
return route("header_route")
.route(header("X-Request-Id", "\\d+"), http())
.before(uri("https://example.org"))
.build();
}
}
如果请求具有名为 X-Request-Id 且值匹配 \d+ 正则表达式(即,该值包含一个或多个数字)的 header,则此路由匹配。
Host 请求谓词
Host 路由谓词工厂接受一个参数:主机名 patterns 的列表。模式是一个 Ant 风格的模式,使用 . 作为分隔符。此谓词匹配与模式匹配的 Host header。以下示例配置了一个 host 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
也支持 URI 模板变量(例如 {sub}.myhost.org)。
如果请求具有 Host header,其值为 www.somehost.org、beta.somehost.org 或 www.anotherhost.org,则此路由匹配。
此谓词将 URI 模板变量(例如前一个示例中定义的 sub)提取为名称和值的映射,并将其放入 ServerRequest.attributes() 中,使用在 MvcUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定义的键。然后,网关处理器过滤函数可以使用这些值。
Method 请求谓词
Method 请求谓词接受一个 methods 参数,该参数是一个或多个要匹配的 HTTP 方法。以下示例配置了一个 method 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
如果请求方法是 GET 或 POST,则此路由匹配。
GatewayRequestPredicates.method 是 RequestPredicates.methods 的一个简单别名。此外,RouterFunctions.Builder API 包含结合了 method 和 path RequestPredicates 的便捷方法。
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
@Configuration
class RouteConfiguration {
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethodAndPath() {
return route("method_and_path_route")
.GET("/mypath", http())
.before(uri("https://example.org"))
.build();
}
}
如果请求方法是 GET 且路径是 /mypath,则此路由匹配。
Path 请求谓词
Path 请求谓词接受两个参数:Spring PathPattern 的 patterns 列表。此请求谓词使用 RequestPredicates.path() 作为底层实现。以下示例配置了一个 path 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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.path;
@Configuration
class RouteConfiguration {
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsPath() {
return route("path_route")
.route(path("/red/{segment}", "/blue/{segment}"), http())
.before(uri("https://example.org"))
.build();
}
}
例如,如果请求路径是 /red/1 或 /red/1/ 或 /red/blue 或 /blue/green,则此路由匹配。
此谓词将 URI 模板变量(例如前一个示例中定义的 segment)提取为名称和值的映射,并将其放入 ServerRequest.attributes() 中,使用在 RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定义的键。然后,网关处理器过滤函数可以使用这些值。
提供了一个工具方法(名为 get),用于更轻松地访问这些变量。以下示例展示了如何使用 get 方法
Map<String, Object> uriVariables = MvcUtils.getUriTemplateVariables(request);
String segment = uriVariables.get("segment");
Query 请求谓词
Query 路由谓词工厂接受两个参数:一个必需的 param 和一个可选的 regexp(一个 Java 正则表达式)。以下示例配置了一个 query 路由谓词
spring:
cloud:
gateway:
mvc:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
如果请求包含一个名为 green 的查询参数,则前一个路由匹配。
spring:
cloud:
gateway:
mvc:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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())
.before(uri("https://example.org"))
.build();
}
}
如果请求包含一个名为 red 的查询参数,其值匹配 gree. 正则表达式,则前一个路由匹配,因此 green 和 greet 都会匹配。
Weight 请求谓词
Weight 路由谓词工厂接受两个参数:group 和 weight(一个 int)。权重是按组计算的。以下示例配置了一个 weight 路由谓词
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
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
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.path;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.weight;
@Configuration
class RouteConfiguration {
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsWeights() {
return route("weight_high")
.route(weight("group1", 8).and(path("/**")), http())
.before(uri("https://weighthigh.org"))
.build().and(
route("weight_low")
.route(weight("group1", 2).and(path("/**")), http())
.before(uri("https://weightlow.org"))
.build());
}
}
此路由会将约 80% 的流量转发到 weighthigh.org,并将约 20% 的流量转发到 weightlow.org。