Spring Cloud Alibaba - 25 Gateway-路由断言工厂Route Predicate Factories谓词工厂示例及源码解析

2022-02-14 08:47:00 浏览数 (1)

文章目录

  • 官网
  • The After Route Predicate Factory
    • 小栗子
    • AfterRoutePredicateFactory源码
  • The Before Route Predicate Factory
    • 小栗子
    • BeforeRoutePredicateFactory源码
  • The Between Route Predicate Factory
    • 小栗子
    • BetweenRoutePredicateFactory源码
  • The Cookie Route Predicate Factory
    • 小栗子
    • CookieRoutePredicateFactory源码
  • The Header Route Predicate Factory
    • 小栗子
    • HeaderRoutePredicateFactory源码
  • The Host Route Predicate Factory
  • The Method Route Predicate Factory
  • The Path Route Predicate Factory
  • The Query Route Predicate Factory
  • The RemoteAddr Route Predicate Factory
  • The Weight Route Predicate Factory
  • 源码

官网

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

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

代码语言:javascript复制
#  网关的After谓词,对应的源码处理AfterRoutePredicateFactory
#作用: 经过网关的所有请求 当前时间>比After阈值  就进行转发
#现在我们是2022年了 currentTime
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

激活配置文件

【测试】

符合预期。

如果我们改下时间呢?

AfterRoutePredicateFactory源码

代码语言:javascript复制
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

代码语言:javascript复制
#目的:测试网关的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源码

代码语言:javascript复制
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

代码语言:javascript复制
# 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源码

代码语言:javascript复制
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

代码语言:javascript复制
#谓词 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源码

核心方法

代码语言:javascript复制
@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

代码语言:javascript复制
#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源码

代码语言:javascript复制
@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

代码语言:javascript复制
#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

代码语言:javascript复制
#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


源码

https://github.com/yangshangwei/SpringCloudAlibabMaster

0 人点赞