Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。

断言就是说: 在 什么条件下 才能进行路由转发

内置断言工厂

SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配体如下: 都是使用在 predicates: 下的


1.基于Datetime类型的断言工厂

此类型的断言根据时间做判断,主要有三个:

  • AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
  • BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
  • BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内

使用方式:

spring:
  cloud:
    gateway:
      routes:
        - id: shop-product            # 路由的唯一标识
          uri: lb://shop-product      # 如果断言成功,将要转发去的地址
          order: 0                    # 优先级,越小优先级越高
          predicates:                 # 断言,满足所有断言,才会进行转发
          	# 在这个时间之后才能进行访问
            - After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]  

2. 基于远程地址的断言工厂

  • RemoteAddrRoutePredicateFactory: 接收一个IP地址段,判断请求主机地址是否在地址段中
- RemoteAddr=192.168.1.1/24 

3. 基于Cookie的断言工厂

  • CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求cookie是否具有给定名称且值与正则表达式匹配。
- Cookie=chocolate, ch.

4. 基于Header的断言工厂

  • HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否具有给定名称且值与正则表达式匹配。
- Header=X-Request-Id, \d+

5.基于Host的断言工厂

  • HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
- Host=**.testhost.org

6.基于Method请求方法的断言工厂

  • MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。
- Method=GET

7.基于Path请求路径的断言工厂

  • PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。
- Path=/foo/{segment}

8.基于Query请求参数的断言工厂

  • QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具有给定名称且值与正则表达式匹配。
- Query=baz, ba. 

9.基于路由权重的断言工厂

  • WeightRoutePredicateFactory:接收一个 [组名,权重] 然后对于同一个组内的路由按照权重转发
gateway:
  routes:
  - id: weight_route1
    uri: host1
    predicates:
      - Path=/product/**
      - Weight=group3, 1
  - id: weight_route2
    uri: host2
    predicates:
      # 路径一致,组一致,权重不同
      - Path=/product/**
      - Weight= group3, 9

自定义路由断言工厂

我们来设定一个场景: 假设我们的应用仅仅让age在(min,max)之间的人来访问。
使用例子来体验一把自定义路由断言工厂

1.定义一个断言工厂,实现断言方法

新建一个类,继承 AbstractRoutePredicateFactory 类,这个类的泛型是 自定义断言工厂的一个内部类叫做Config 是一个固定的名字,在Config 类中定义自定义断言需要的一些属性,并且自定义断言工厂使用 @Component 注解,交给spring容器创建

这里的age是通过请求参数(request.getQueryParams())获取的,这个可以根据需要进行调整。你需要从请求头获取,就通过request.getHeaders() 获取即可。

@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
    public AgeRoutePredicateFactory() {
        super(AgeRoutePredicateFactory.Config.class);
    }

    //读取配置文件中的内容并配置给配置类中的属性
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("minAge","maxAge");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            // 获取请求参数中的 age 属性
            String age = exchange.getRequest().getQueryParams().getFirst("age");
            if(StringUtils.isNotEmpty(age)) {
                try {
                    int a = Integer.parseInt(age);
                    boolean res = a >= config.minAge && a <= config.maxAge;
                    return res;
                } catch (Exception e) {
                    System.out.println("输入的参数不是数字格式");
                }
            }
            return false;
        };
    }

    @Validated
    public static class Config {
        private Integer minAge;
        private Integer maxAge;

        public Integer getMinAge() {
            return minAge;
        }

        public void setMinAge(Integer minAge) {
            this.minAge = minAge;
        }

        public Integer getMaxage() {
            return maxAge;
        }

        public void setMaxage(Integer maxage) {
            this.maxAge = maxage;
        }
    }
}

在这个自定义断言中,.Config 中有两个属性 minAge 和 maxAge
apply() 方法中编写断言的比较逻辑

2. 在yml中使用自定义断言

在yml文件中使用自定义断言。

spring:
  cloud:
    gateway:
      routes:
        - id: shop-product            # 路由的唯一标识
          uri: lb://shop-product      # 如果断言成功,将要转发去的地址
          order: 0                    # 优先级,越小优先级越高
          predicates:                 # 断言,满足所有断言,才会进行转发
            - Path=/product/**        # 注意:这是使用= 不是:
            # 自定义断言,第一个参数对应minAge,第二个参数对应maxAge
            - Age=18, 60

从这里的演示应该可以看出来,自定义断言与系统自带断言的配置,在yml中只需要使用首部名称,默认忽略类名中的 RoutePredicateFactory

例如自定义的断言 AgeRoutePredicateFactory 在使用的时候,就是通过 -Age 进行指定的。



效果:
在这里插入图片描述
在这里插入图片描述

ok,就是这样

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐