閘道器請求謂詞

Spring Cloud Gateway MVC 作為 Spring WebMvc.fn 的 HandlerMapping 基礎設施的一部分來匹配路由。Spring Cloud Gateway 複用了許多 RequestPredicate 實現,幷包含了其他自定義的 RequestPredicate 實現。所有這些謂詞都匹配 HTTP 請求的不同屬性。您可以透過 RequestPredicate.and()RequestPredicate.or() 方法組合多個路由謂詞工廠。

After 請求謂詞

After 路由謂詞工廠接受一個引數,即一個 datetime(一個 Java 的 ZonedDateTime 物件)。此謂詞匹配發生在指定日期時間之後的請求。以下示例配置了一個 after 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: after_route
          uri: https://example.org
          predicates:
          - After=2017-01-20T17:42:47.789-07:00[America/Denver]
GatewaySampleApplication.java
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 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: before_route
          uri: https://example.org
          predicates:
          - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
GatewaySampleApplication.java
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 路由謂詞工廠接受兩個引數,datetime1datetime2,它們都是 Java 的 ZonedDateTime 物件。此謂詞匹配發生在 datetime1 之後和 datetime2 之前的請求。datetime2 引數必須在 datetime1 之後。以下示例配置了一個 between 路由謂詞

application.yml
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]
GatewaySampleApplication.java
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 的 name 和一個 regexp(一個 Java 正則表示式)。此謂詞匹配具有給定名稱且值匹配正則表示式的 cookie。以下示例配置了一個 cookie 路由謂詞工廠

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: cookie_route
          uri: https://example.org
          predicates:
          - Cookie=chocolate, ch.p
GatewaySampleApplication.java
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 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: header_route
          uri: https://example.org
          predicates:
          - Header=X-Request-Id, \d+
GatewaySampleApplication.java
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 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: host_route
          uri: https://example.org
          predicates:
          - Host=**.somehost.org,**.anotherhost.org
GatewaySampleApplication.java
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.orgbeta.somehost.orgwww.anotherhost.org,則此路由匹配。

此謂詞將 URI 模板變數(例如前一個示例中定義的 sub)提取為名稱和值的對映,並將其放入 ServerRequest.attributes() 中,使用在 MvcUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定義的鍵。然後,閘道器處理器過濾函式可以使用這些值。

Method 請求謂詞

Method 請求謂詞接受一個 methods 引數,該引數是一個或多個要匹配的 HTTP 方法。以下示例配置了一個 method 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: method_route
          uri: https://example.org
          predicates:
          - Method=GET,POST
GatewaySampleApplication.java
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();
    }
}

如果請求方法是 GETPOST,則此路由匹配。

GatewayRequestPredicates.methodRequestPredicates.methods 的一個簡單別名。此外,RouterFunctions.Builder API 包含結合了 methodpath RequestPredicates 的便捷方法。

GatewaySampleApplication.java
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 PathPatternpatterns 列表。此請求謂詞使用 RequestPredicates.path() 作為底層實現。以下示例配置了一個 path 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: path_route
          uri: https://example.org
          predicates:
          - Path=/red/{segment},/blue/{segment}
GatewaySampleApplication.java
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 路由謂詞

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: query_route
          uri: https://example.org
          predicates:
          - Query=green
GatewaySampleApplication.java
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 的查詢引數,則前一個路由匹配。

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: query_route
          uri: https://example.org
          predicates:
          - Query=red, gree.
GatewaySampleApplication.java
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. 正則表示式,則前一個路由匹配,因此 greengreet 都會匹配。

Weight 請求謂詞

Weight 路由謂詞工廠接受兩個引數:groupweight(一個 int)。權重是按組計算的。以下示例配置了一個 weight 路由謂詞

application.yml
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
GatewaySampleApplication.java
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