Between 路由断言工厂需要两个参数:datetime1 和 datetime2,它们都是 java ZonedDateTime 对象。语法如下:
Between=datetime1, datetime2
该断言匹配发生在 datetime1 之后和日期 datetime2 之前的请求,datetime2 参数必须在 datetime1 之后。例如:
spring: cloud: gateway: 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]
上面配置中,between_route 路由将仅仅接收 2017年1月20日 17:42 山地时间(Denver 丹佛)之后至 2017年1月21日 17:42 山地时间(Denver 丹佛)之前提出的任何请求。
将“Gateway 搭建网关服务”项目的配置文件 bootstrap.yml 内容使用如下配置替换:
server: # 网关端口 port: 9000 spring: application: # 服务名称 name: gateway-demo01 cloud: # nacos nacos: discovery: server-addr: localhost:8848 username: nacos password: nacos group: DEFAULT_GROUP # 网关路由配置 gateway: # 网关路由配置 routes: # 路由id,自定义,只要唯一集合 - id: service-order # 路由的目标地址,lb 就是负载均衡,后面跟服务名 # 需要集成 nacos 等服务注册中心 uri: lb://service-order # 路由断言,也就是判断请求是否符合路由规则的条件 predicates: # Between断言:匹配 2023-12-09 22点~23点之间的请求 - Between=2023-12-09T22:00:00.000-08:00[Asia/Shanghai],2023-12-09T23:00:00.000-08:00[Asia/Shanghai]
重启网关服务,使用 Postman 访问订单接口,如下图:
从上图可知,请求成功,因为当前时间为 2023-12-09 22:15:00。如果我们将配置修改为如下:
- Between=2023-12-09T22:00:00.000-08:00[Asia/Shanghai],2023-12-09T22:15:00.000-08:00[Asia/Shanghai]
再次重启网关服务,访问订单接口如下图:
从上图可知,调用失败,为当前时间并不在 2023-12-09 22:00 ~ 2023-12-09 22:15 之间。
下面是 Between 路由断言工厂源码:
package org.springframework.cloud.gateway.handler.predicate; // ... public class BetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<BetweenRoutePredicateFactory.Config> { public static final String DATETIME1_KEY = "datetime1"; 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) { // 获取配置的日期 ZonedDateTime datetime1 = config.datetime1; ZonedDateTime datetime2 = config.datetime2; // 验证 datetime1 必须在 datetime2 之前 Assert.isTrue(datetime1.isBefore(datetime2), config.datetime1 + " must be before " + config.datetime2); return exchange -> { // 根据当前日期进行计算 // datetime1 < now < datetime2 final ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(datetime1) && now.isBefore(datetime2); }; } @Validated public static class Config { @NotNull private ZonedDateTime datetime1; @NotNull private ZonedDateTime datetime2; // 配置信息 } }