spring cloud gateway源码(六)Predicate

在Spring Cloud Gateway中,默认添加的predicate是:PathRoutePredicateFactory。在Spring Cloud Gateway中有许多的Predicate,他们的功能各异。下面我们一起分析一下。

一、获取predicate

在RouteDefinitionRouteLocator类的getRoutes()方法中:

	@Override
	public Flux<Route> getRoutes() {
		return this.routeDefinitionLocator.getRouteDefinitions()
				.map(this::convertToRoute)

上面再获取到RouteDefinition后,会调用convertToRoute()方法,通过这个方法就是去获取了route中的predicates。

	private Route convertToRoute(RouteDefinition routeDefinition) {
		AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);

我们进入combinePredicate方法中看下

	private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
		List<PredicateDefinition> predicates = routeDefinition.getPredicates();
		AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0));

		for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
			AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
			predicate = predicate.and(found);
		}

		return predicate;
	}

可以看到方法中先获取第一个predicate,再获取第二个predicate,调用and方法整合两个predicate为一个predicate

二、整合predicate

整合代码为predicate的and方法

	default AsyncPredicate<T> and(AsyncPredicate<? super T> other) {
		Objects.requireNonNull(other, "other must not be null");

		return t -> Flux.zip(apply(t), other.apply(t))
				.map(tuple -> tuple.getT1() && tuple.getT2());
	}

整合中用到了Tuple2类,就是调用的时候,验证两个predicate的apply()方法是否都通过,做&&运算。通过这种方式重复整合,可以做到验证多个predicate。

三、predicates

Spring Cloud Gateway默认只用了一个Predicate,PathRoutePredicateFactory,其实还有其他Predicate可以使用,他们分别如下:

predicates
BeforeRoutePredicateFactory
在某个时间点前有用的路由
AfterRoutePredicateFactory
在某个时间点后有用的路由
BetweenRoutePredicateFactory
在两个时间点间有用的路由
CloudFoundryRouteServiceRoutePredicateFactory
用于云计算的路由(不动)
CookieRoutePredicateFactory
验证cookie的路由
HeaderRoutePredicateFactory
验证header的路由
HostRoutePredicateFactory
验证host的路由
MethodRoutePredicateFactory
验证请求方式的路由
PathRoutePredicateFactory
验证path的路由
QueryRoutePredicateFactory
验证请求参数的路由
ReadBodyPredicateFactory
验证body的路由
RemoteAddrRoutePredicateFactory
验证远程访问地址的路由
WeightRoutePredicateFactory
权重的路由

四、重点

需要说明的是,这些Predicate都是已经写好的代码,要填写适当的参数。例如验证header的路由,只能验证某个header是否为某个值,而且一旦使用,所有的route都要走这个路由规则。所以predicate是做通用配置用的,而不是用作个性化配置的。

五、使用方式举例

    @Bean
    public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
        PredicateDefinition predicate = new PredicateDefinition();
        predicate.setName(normalizeRoutePredicateName(WeightRoutePredicateFactory.class));
        predicate.addArg("weight.group", "serviceId");

        properties.getPredicates().add(predicate);

        return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
    }

猜你喜欢

转载自blog.csdn.net/lz710117239/article/details/81322783