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

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
云解析 DNS,旗舰版 1个月
传统型负载均衡 CLB,每月750个小时 15LCU
简介: 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

相关文章
|
1月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
142 1
|
22天前
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
681 111
|
9天前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
160 70
|
21天前
|
人工智能 Java 决策智能
Java版Manus实现来了,Spring AI Alibaba发布开源OpenManus实现
此次官方发布的 Spring AI Alibaba OpenManus 实现,包含完整的多智能体任务规划、思考与执行流程,可以让开发者体验 Java 版本的多智能体效果。它能够根据用户的问题进行分析,操作浏览器,执行代码等来完成复杂任务等。
663 57
|
22天前
|
数据采集 人工智能 Java
使用 Ollama 本地模型与 Spring AI Alibaba 的强强结合,打造下一代 RAG 应用
使用 Ollama 本地模型与 Spring AI Alibaba 的强强结合,打造下一代 RAG 应用
190 22
|
1月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
157 29
|
2月前
|
存储 人工智能 开发框架
Spring AI Alibaba 应用框架挑战赛圆满落幕,恭喜获奖选手
第二届开放原子大赛 Spring AI Alibaba 应用框架挑战赛决赛于 2 月 23 日在北京圆满落幕。
160 19
|
2月前
|
人工智能 Cloud Native 安全
DeepSeek + Higress AI 网关/Spring AI Alibaba 案例征集
诚挚地感谢每一位持续关注并使用 Higress 和 Spring AI Alibaba 的朋友,DeepSeek + Higress AI 网关/Spring AI Alibaba 案例征集中。
298 22
|
2月前
|
人工智能 Java API
支持 40+ 插件,Spring AI Alibaba 简化智能体私有数据集成
通过使用社区官方提供的超过 20 种 RAG 数据源和 20 种 Tool Calling 接口,开发者可以轻松接入多种外部数据源(如 GitHub、飞书、云 OSS 等)以及调用各种工具(如天气预报、地图导航、翻译服务等)。这些默认实现大大简化了智能体的开发过程,使得开发者无需从零开始,便可以快速构建功能强大的智能体系统。通过这种方式,智能体不仅能够高效处理复杂任务,还能适应各种应用场景,提供更加智能、精准的服务。
604 13
|
2月前
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
619 1

热门文章

最新文章

推荐镜像

更多