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

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

6735aa4777de402592fbe82e8b40ee3d.png

官网


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


efda0395c2c841c290c57e6b7fe8c02c.png


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


bc324e779555424785f12365cfaa960b.png


小栗子


我们还是继续老工程 ,启动

artisan-cloud-gateway 【8888】

artisan-cloud-gateway-order

artisan-cloud-gateway-product


网关配置

application-after_route.yml

#  网关的After谓词,对应的源码处理AfterRoutePredicateFactory
#作用: 经过网关的所有请求 当前时间>比After阈值  就进行转发
#现在我们是2022年了 currentTime<After阈值,所以网关不会进行转发,而返回404spring:
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<After阈值,所以网关不会进行转发 .

激活配置文件


ed80b0cf416f4559850e6eb9d86a2dd9.png

【测试】

86d3854e4a0d49d58941c26d3d8e8fab.png

符合预期。

如果我们改下时间呢?f4ed71bd62d1431d9be69770f38d2be3.png


550cb642210f44af8d7e2ef186675c18.png

AfterRoutePredicateFactory源码

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


7c31b93da03041d487716752eea94fcd.png


小栗子

application-before_route.yml

#目的:测试网关的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源码

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

8ed70d6a35d0441faacc62b599a8b32f.png


小栗子

application-between-route.yml

# 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源码

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


1a9555dc649d42f6aaec0595fdf94de0.png


小栗子

application-cookie-route.yml

#谓词 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源码

核心方法

@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-factory0ad5333f223d4a22a0fb84ed5d5ef0fc.png


小栗子

application-header-route.yml

#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源码

@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


678c802c65564cefa96df513a115754b.png


#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


a612ecb296e848bcb081271a2e5dae64.png

#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


a03fe6b135eb44edb8b26610fecc7b79.png


850a282ecf414f619917dd85f063774c.png

The Query Route Predicate Factory

d565ec660b684e15bc0a66f82cab9719.png

3f7c72b678784e93a0c3a676d79c97d7.png


The RemoteAddr Route Predicate Factory


a51ee8e25a414238bf8a3dd99a655fea.png

The Weight Route Predicate Factory


755ac97c8a2a43dab5c0a11563f57af1.png


源码


https://github.com/yangshangwei/SpringCloudAlibabMaster

相关文章
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
3221 1
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
1657 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
11月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
797 0
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1480 29
|
人工智能 文字识别 自然语言处理
保单AI识别技术及代码示例解析
车险保单包含基础信息、车辆信息、人员信息、保险条款及特别约定等关键内容。AI识别技术通过OCR、文档结构化解析和数据校验,实现对保单信息的精准提取。然而,版式多样性、信息复杂性、图像质量和法律术语解析是主要挑战。Python代码示例展示了如何使用PaddleOCR进行保单信息抽取,并提出了定制化训练、版式分析等优化方向。典型应用场景包括智能录入、快速核保、理赔自动化等。未来将向多模态融合、自适应学习和跨区域兼容性发展。
1153 29
|
JSON 前端开发 搜索推荐
关于商品详情 API 接口 JSON 格式返回数据解析的示例
本文介绍商品详情API接口返回的JSON数据解析。最外层为`product`对象,包含商品基本信息(如id、name、price)、分类信息(category)、图片(images)、属性(attributes)、用户评价(reviews)、库存(stock)和卖家信息(seller)。每个字段详细描述了商品的不同方面,帮助开发者准确提取和展示数据。具体结构和字段含义需结合实际业务需求和API文档理解。
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
490 18
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
2528 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
JSON 缓存 API
解析电商商品详情API接口系列,json数据示例参考
电商商品详情API接口是电商平台的重要组成部分,提供了商品的详细信息,支持用户进行商品浏览和购买决策。通过合理的API设计和优化,可以提升系统性能和用户体验。希望本文的解析和示例能够为开发者提供参考,帮助构建高效、可靠的电商系统。
725 12

热门文章

最新文章

推荐镜像

更多
  • DNS