官网
Spring Cloud Gateway 将路由匹配为 Spring WebFluxHandlerMapping基础架构的一部分。Spring Cloud Gateway 包含许多内置的路由谓词工厂。所有这些谓词都匹配 HTTP 请求的不同属性。我们可以将多个路由谓词工厂与逻辑and语句结合起来。
The After Route Predicate Factory
https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-after-route-predicate-factory
小栗子
我们还是继续老工程 ,启动
artisan-cloud-gateway 【8888】
artisan-cloud-gateway-order
artisan-cloud-gateway-product
【网关配置】
application-after_route.yml
# 网关的After谓词,对应的源码处理AfterRoutePredicateFactory #作用: 经过网关的所有请求 当前时间>比After阈值 就进行转发 #现在我们是2022年了 currentTime<After阈值,所以网关不会进行转发,而返回404spring: spring: cloud: gateway: #gateway routes: - id: after_route # id 确保唯一 uri: lb://artisan-cloud-gateway-order # nacos上的 注册地址 predicates: - After=2025-02-13T18:27:28.309+08:00[Asia/Shanghai]
currentTime<After阈值,所以网关不会进行转发 .
激活配置文件
【测试】
符合预期。
如果我们改下时间呢?
AfterRoutePredicateFactory源码
public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory<AfterRoutePredicateFactory.Config> { /** * DateTime key. */ public static final String DATETIME_KEY = "datetime"; public AfterRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Collections.singletonList(DATETIME_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { final ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(config.getDatetime()); } @Override public String toString() { return String.format("After: %s", config.getDatetime()); } }; } public static class Config { @NotNull private ZonedDateTime datetime; public ZonedDateTime getDatetime() { return datetime; } public void setDatetime(ZonedDateTime datetime) { this.datetime = datetime; } } }
核心方法,apply,比较简单。
The Before Route Predicate Factory
https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-before-route-predicate-factory
小栗子
application-before_route.yml
#目的:测试网关的Before谓词,对应的源码处理BeforeRoutePredicateFactory #作用: 经过网关的所有请求当前时间 比Before=2021-02-13T18:27:28.309+08:00[Asia/Shanghai] 小 就进行转发 #现在2022年了 时间比配置的阈值大,所以我们不会进行转发,而返回404 #2021-02-13T18:27:28.309+08:00[Asia/Shanghai] 这个时间怎么获取的呢? --- System.out.println(ZonedDateTime.now()) spring: cloud: gateway: #gateway routes: - id: before_route # id 确保唯一 uri: lb://artisan-cloud-gateway-order predicates: - Before=2023-02-13T18:27:28.309+08:00[Asia/Shanghai]
BeforeRoutePredicateFactory源码
public class BeforeRoutePredicateFactory extends AbstractRoutePredicateFactory<BeforeRoutePredicateFactory.Config> { /** * DateTime key. */ public static final String DATETIME_KEY = "datetime"; public BeforeRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Collections.singletonList(DATETIME_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { final ZonedDateTime now = ZonedDateTime.now(); return now.isBefore(config.getDatetime()); } @Override public String toString() { return String.format("Before: %s", config.getDatetime()); } }; } public static class Config { private ZonedDateTime datetime; public ZonedDateTime getDatetime() { return datetime; } public void setDatetime(ZonedDateTime datetime) { this.datetime = datetime; } } }
The Between Route Predicate Factory
https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-between-route-predicate-factory
小栗子
application-between-route.yml
# Between谓词 BetweenRoutePredicateFactory # 就是经过网关请求的当前时间 currentTime 满足 # Between startTime < currentTime < Between EndTime 才进行转发 spring: cloud: gateway: routes: - id: between-route #id必须要唯一 uri: lb://artisan-cloud-gateway-order # 这里可以使用负载均衡的写法 predicates: - Between=2020-02-13T18:27:28.309+08:00[Asia/Shanghai],2025-02-13T18:27:28.309+08:00[Asia/Shanghai]
BetweenRoutePredicateFactory源码
public class BetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<BetweenRoutePredicateFactory.Config> { /** * DateTime 1 key. */ public static final String DATETIME1_KEY = "datetime1"; /** * DateTime 2 key. */ public static final String DATETIME2_KEY = "datetime2"; public BetweenRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(DATETIME1_KEY, DATETIME2_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()), config.getDatetime1() + " must be before " + config.getDatetime2()); return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { final ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(config.getDatetime1()) && now.isBefore(config.getDatetime2()); } @Override public String toString() { return String.format("Between: %s and %s", config.getDatetime1(), config.getDatetime2()); } }; } @Validated public static class Config { @NotNull private ZonedDateTime datetime1; @NotNull private ZonedDateTime datetime2; public ZonedDateTime getDatetime1() { return datetime1; } public Config setDatetime1(ZonedDateTime datetime1) { this.datetime1 = datetime1; return this; } public ZonedDateTime getDatetime2() { return datetime2; } public Config setDatetime2(ZonedDateTime datetime2) { this.datetime2 = datetime2; return this; } } }
The Cookie Route Predicate Factory
https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-cookie-route-predicate-factory
小栗子
application-cookie-route.yml
#谓词 Cookie 源码 CookieRoutePredicateFactory #表示通过网关的请求 必须带入包含了Cookie name=Company value=Artisan #才转发请求 spring: cloud: gateway: routes: - id: cookie-route #id必须要唯一 uri: lb://artisan-cloud-gateway-order # 这里可以使用负载均衡的写法 predicates: #当我们的请求中包含了Cookie name=Company value=Artisan #才转发请求 - Cookie=Company,Artisan
CookieRoutePredicateFactory源码
核心方法
@Override public Predicate<ServerWebExchange> apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange exchange) { List<HttpCookie> cookies = exchange.getRequest().getCookies() .get(config.name); if (cookies == null) { return false; } for (HttpCookie cookie : cookies) { if (cookie.getValue().matches(config.regexp)) { return true; } } return false; } @Override public String toString() { return String.format("Cookie: name=%s regexp=%s", config.name, config.regexp); } }; }
The Header Route Predicate Factory
https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-header-route-predicate-factory
小栗子
application-header-route.yml
#Header谓词 源码HeaderRoutePredicateFactory #说明请求经过网关 必须带入 #header的k=X-Request-appId v=Artisan才会被转发 spring: cloud: gateway: routes: - id: header-route #id必须要唯一 uri: lb://artisan-cloud-gateway-order predicates: - Header=X-Request-appId,Artisan
HeaderRoutePredicateFactory源码
@Override public Predicate<ServerWebExchange> apply(Config config) { boolean hasRegex = !StringUtils.isEmpty(config.regexp); return new GatewayPredicate() { @Override public boolean test(ServerWebExchange exchange) { List<String> values = exchange.getRequest().getHeaders() .getOrDefault(config.header, Collections.emptyList()); if (values.isEmpty()) { return false; } // values is now guaranteed to not be empty if (hasRegex) { // check if a header value matches return values.stream() .anyMatch(value -> value.matches(config.regexp)); } // there is a value and since regexp is empty, we only check existence. return true; } @Override public String toString() { return String.format("Header: %s regexp=%s", config.header, config.regexp); } }; }
The Host Route Predicate Factory
#Host谓词 源码HostRoutePredicateFactory #说明请求http://localhost:8888/selectOrderInfoById/1的 #Host必须满足www.artisan.com:8888或者localhost:8888才会 #转发到http://artisan-cloud-gateway-order/selectOrderInfoById/1 #而127.0.0.1不会被转发 spring: cloud: gateway: routes: - id: host-route #id必须要唯一 uri: lb://artisan-cloud-gateway-order predicates: - Host=www.artisan.com:8888,localhost:8888
The Method Route Predicate Factory
#Http请求方法的谓词 Method 源码 MethodRoutePredicateFactory #表示经过网关的请求 只有post方式才能被转发 spring: cloud: gateway: routes: - id: method #id必须要唯一 uri: lb://artisan-cloud-gateway-order predicates: #当前请求的方式 http://localhost:8888/selectOrderInfoById/1 是Post才会被转发 #到http://artisan-cloud-gateway-order/selectOrderInfoById/1 - Method=Post
The Path Route Predicate Factory
The Query Route Predicate Factory
The RemoteAddr Route Predicate Factory
The Weight Route Predicate Factory