一、概述

  Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础结构的一部分进行匹配。 Spring Cloud Gateway包含许多内置的Route Predicate Factories。所有这些谓词都匹配HTTP请求的不同属性。多路线谓词工厂可以组合,并通过逻辑and。

  路由选择是通过Predicate函数式接口进行判断当前路由是否满足给定条件。

  附注:关于jdk8的Predicate
  Predicate<T> 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
add--与、or--或、negate--非
  boolean test(T t); 判断
  Predicate<T> and(Predicate<? super T> other) 接收一个Predicate类型,也就是将传入的条件和当前条件以并且(AND)的关系组合
  Predicate<T> or(Predicate<? super T> other)接收一个Predicate类型,也就是将传入的条件和当前条件以或(OR)的关系组合
  更多参看:https://www.cnblogs.com/bjlhx/p/9711292.html

1.1、路由谓词创建及使用

1️⃣、加载路由中的Predicate

  在路由定位器中以及看到了通过路由定义转换路由方法,其中包含了通过谓语定义(PredicateDefinition)转换谓语(Predicate)的部分,在RouteDefinitionRouteLocator类中源码如下:

/**
* 返回组合的谓词
* @param routeDefinition
* @return
*/
private Predicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
//获取RouteDefinition中的PredicateDefinition集合
List<PredicateDefinition> predicates = routeDefinition.getPredicates(); Predicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0)); for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
Predicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
//返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND
predicate = predicate.and(found);
} return predicate;
} /**
* 获取一个谓语定义(PredicateDefinition)转换的谓语
* @param route
* @param predicate
* @return
*/
@SuppressWarnings("unchecked")
private Predicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) {
//获取谓语创建工厂
RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
if (factory == null) {
throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName());
}
//获取参数
Map<String, String> args = predicate.getArgs();
if (logger.isDebugEnabled()) {
logger.debug("RouteDefinition " + route.getId() + " applying "
+ args + " to " + predicate.getName());
} //组装参数
Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
//构建创建谓语的配置信息
Object config = factory.newConfig();
ConfigurationUtils.bind(config, properties,
factory.shortcutFieldPrefix(), predicate.getName(), validator);
if (this.publisher != null) {
this.publisher.publishEvent(new PredicateArgsEvent(this, route.getId(), properties));
}
//通过谓语工厂构建谓语
return factory.apply(config);
}
  • 获取路由定义(routeDefinition)所有的谓语定位(PredicateDefinition)
  • 以此根据谓语定义(PredicateDefinition)查找谓语对于的创建工厂(RoutePredicateFactory) 创建谓语
  • 通过 Predicate<T>接口 and方法合并谓语集合返回一个新的复合谓语

2️⃣、使用路由Predicate判断路由是否可用

  在Spring-Cloud-Gateway之请求处理流程里,在handlerMapping中通过路由定位器获取所有路由,并过滤掉谓语判断失败的路由,最终获取满足条件的路由

protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
//通过路由定位器获取路由信息
return this.routeLocator.getRoutes()
.filter(route -> {
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, route.getId());
//返回通过谓语过滤的路由信息
return route.getPredicate().test(exchange);
});
}

  通过上面两步可以看到了整个路由的条件创建以及使用的地方以及流程,Spring-Cloud-Gateway通过Predicate接口完成简单条件组合以及判断。

1.2、RoutePredicateFactory 路由谓词工厂

  Spring-Cloud-Gateway通过RoutePredicateFactory创建Predicate。其中预制了很多RoutePredicateFactory使其可以通过简单的配置就可以创建出理想的Predicate。
查看类Uml图
  

按照子类功能划分:

  

1️⃣、MethodRoutePredicateFactory

/**
* 请求方式(GET,POST,DEL,PUT)校验匹配创建工厂
*/
public class MethodRoutePredicateFactory extends AbstractRoutePredicateFactory<MethodRoutePredicateFactory.Config> { public static final String METHOD_KEY = "method";
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
//获取当前请求的HttpMethod
HttpMethod requestMethod = exchange.getRequest().getMethod();
//校验请求HttpMethod与配置是否一致
return requestMethod == config.getMethod();
};
} public static class Config {
/**
* http 请求Method
*/
private HttpMethod method; public HttpMethod getMethod() {
return method;
} public void setMethod(HttpMethod method) {
this.method = method;
}
}
}

配置示例

spring:
cloud:
gateway:
routes:
# =====================================
- id: method_route
uri: http://example.org
predicates:
- Method=GET

过程:

  • Method=GET 会被解析成PredicateDefinition对象 (name =Method ,args= GET)
  • 通过PredicateDefinition的Name找到MethodRoutePredicateFactory工厂
  • 通过 PredicateDefinition 的args 创建Config对象(HttpMethod=GET)
  • 通过 MethodRoutePredicateFactory工厂的apply方法传入config创建Predicate对象。

1.3、全部谓词配置

1.3.1、After Route Predicate Factory

  此谓词匹配当前日期时间之后发生的请求。

  application.yml

spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]

1.3.2、Before Route Predicate Factory

  此谓词匹配在当前日期时间之前发生的请求。

  application.yml

spring:
cloud:
gateway:
routes:
- id: before_route
uri: http://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

1.3.3、Between Route Predicate Factory

  此谓词匹配datetime1之后和datetime2之前发生的请求。 datetime2参数必须在datetime1之后。

  application.yml

spring:
cloud:
gateway:
routes:
- id: between_route
uri: http://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

1.3.4、Cookie Route Predicate Factory

  Cookie Route Predicate Factory有两个参数,cookie名称和正则表达式。此谓词匹配具有给定名称且值与正则表达式匹配的cookie。

  application.yml

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://example.org
predicates:
- Cookie=chocolate, ch.p

  此路由匹配请求有一个名为chocolate的cookie,其值与ch.p正则表达式匹配。

1.3.5、Header Route Predicate Factory

  Header Route Predicate Factory有两个参数,标题名称和正则表达式。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。

  application.yml

spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+

  如果请求具有名为X-Request-Id的标头,则该路由匹配,其值与\ d +正则表达式匹配(具有一个或多个数字的值)。

1.3.6、Host Route Predicate Factory

  Host Route Predicate Factory采用一个参数:主机名模式。该模式是一种Ant样式模式“.”作为分隔符。此谓词匹配与模式匹配的Host标头。

  application.yml

spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Host=**.somehost.org

  如果请求的主机头具有值www.somehost.org或beta.somehost.org,则此路由将匹配。

1.3.7、Method Route Predicate Factory

  Method Route Predicate Factory采用一个参数:要匹配的HTTP方法。

spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://example.org
predicates:
- Method=GET

1.3.8、Path Route Predicate Factory

spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Path=/foo/{segment}

/foo/1 or /foo/bar.

1.3.9、Query Route Predicate Factory

Query Route Predicate Factory有两个参数:一个必需的参数和一个可选的正则表达式。

spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=baz

如果请求包含baz查询参数,则此路由将匹配。

spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=foo, ba.

如果请求包含其值与ba匹配的foo查询参数,则此路由将匹配。 regexp,所以bar和baz匹配。

1.3.10、RemoteAddr Route Predicate Factory

RemoteAddr Route Predicate Factory采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如, 192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)。

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://example.org
predicates:
- RemoteAddr=192.168.1.1/24

如果请求的远程地址是例如192.168.1.10,则此路由将匹配。

008-spring cloud gateway-路由谓词RoutePredicate、RoutePredicateFactory的更多相关文章

  1. SpringCloud无废话入门05:Spring Cloud Gateway路由、filter、熔断

    1.什么是路由网关 截至目前为止的例子中,我们创建了一个service,叫做:HelloService,然后我们把它部署到了两台服务器(即提供了两个provider),然后我们又使用ribbon将其做 ...

  2. Spring Cloud Gateway - 路由法则

    1. After Route Predicate Factory 输入一个参数:时间,匹配该时间之后的请求,示例配置: spring: cloud: gateway: routes: - id: af ...

  3. Spring Cloud Alibaba学习笔记(16) - Spring Cloud Gateway 内置的路由谓词工厂

    Spring Cloud Gateway路由配置的两种形式 Spring Cloud Gateway的路由配置有两种形式,分别是路由到指定的URL以及路由到指定的微服务,在上文博客的示例中我们就已经使 ...

  4. spring cloud gateway 深入了解 - Predicate

    文章来源 spring cloud gateway 通过谓词(Predicate)来匹配来自用户的请求 为了方便,使用postman测试不同的谓词的效果 路径谓词(Predicate)—— 最简单的谓 ...

  5. 看完就会的Spring Cloud Gateway

    在前面几节,我给大家介绍了当一个系统拆分成微服务后,会产生的问题与解决方案:服务如何发现与管理(Nacos注册中心实战),服务与服务如何通信(Ribbon, Feign实战) 今天我们就来聊一聊另一个 ...

  6. Spring Cloud Gateway 没有链路信息,我 TM 人傻了(上)

    本系列是 我TM人傻了 系列第五期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...

  7. Spring Cloud Gateway 没有链路信息,我 TM 人傻了(中)

    本系列是 我TM人傻了 系列第五期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...

  8. Spring Cloud Gateway夺命连环10问?

    大家好,我是不才陈某~ 最近有很多小伙伴私信我催更 <Spring Cloud 进阶>,陈某也总结了一下,最终原因就是陈某之前力求一篇文章将一个组件重要知识点讲透,这样导致了文章篇幅很长, ...

  9. Spring Cloud Gateway(六):路由谓词工厂 RoutePredicateFactory

    本文基于 spring cloud gateway 2.0.1 1.简介 Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 ...

  10. Spring Cloud Alibaba学习笔记(17) - Spring Cloud Gateway 自定义路由谓词工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的路由谓词工厂,但是如果这些内置的路由谓词工厂不能满足业务需求的话,我们可以自定义路由谓词工厂来实现特定的需求. 例如有某个服务 ...

随机推荐

  1. PHP垃圾回收机制防止内存溢出

    PHP语言同其他语言一样,具有垃圾回收机制.那么今天我们要为大家讲解的内容就是关于PHP垃圾回收机制的相关问题.希望对大家有所帮助. 一.PHP 垃圾回收机制(Garbage Collector 简称 ...

  2. linux apache下虚拟主机配置方法

    假设VPS的IP是58.130.17.168,有两个域名指向该IP,分别是domain1.com, domain2.com, 修改/etc/httpd/conf/httpd.conf,在文件的最后加入 ...

  3. JS动态设置确认弹窗

    多次使用确认弹窗 <!--START 确认收货--> <div class="popout-boxbg out" id="delivery_goods& ...

  4. Android开发训练之第五章第五节——Resolving Cloud Save Conflicts

    Resolving Cloud Save Conflicts IN THIS DOCUMENT Get Notified of Conflicts Handle the Simple Cases De ...

  5. WP8.1学习系列(第十章)——中心控件Hub设计指南

    Windows Phone 应用商店应用中的中心控件指南   在本文中 说明 示例 用法指南 设计指南 相关主题 重要的 API Hub (XAML) HubSection (XAML) 说明 中心控 ...

  6. 【linux系列】压缩和解压缩tar

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...

  7. create-react-app项目中的eslint

    "no-multi-spaces": 1, //禁止多个空格 "jsx-quotes": 1, //此规则强制在JSX属性中一致使用双引号或单引号 " ...

  8. slf4j + log4j 是如何初始化的

    SLF4J的全称是 Simple Logging Facade for Java(简单java日志门面) SLF4J自己不提供具体的日志功能实现,只是提供了一个统一的日志门面,在这个统一的门面之下,用 ...

  9. gem install 和 bundle 区别

    bundle install 在设置了所有包含在Gemfile中的东西.你也可以传递参数. 如果在production模式下,你很清晰的区分了每个app需要的gems. gem install 则安装 ...

  10. 【BZOJ3774】最优选择 最小割

    [BZOJ3774]最优选择 Description 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择 ...