SpringCloud 2023 Gateway的Predicate配置详解、自定义Route Predicate Factory

news2024/12/24 21:11:54

目录

  • 1. Predicate Factories介绍
  • 2. 常用的内置Route Predicate使用
    • 2.1 配置语法说明
    • 2.2 配置使用
  • 3. 自定义Route Predicate Factory
    • 3.1 实现步骤:
    • 3.2 实现代码如下:
    • 3.3 application.yml配置
    • 3.4 测试

1. Predicate Factories介绍

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。包含共12种内置的Route Predicate Factory,可以配置多个Route Predicate Factory,用逻辑and进行组合,如果HTTP请求的不同属性满足条件,则跳转到指定的route路由
Predicate Factories介绍

启动Spring Cloud Gateway服务时,日志会打印加载的Route Predicate Factory,如下所示。所有Route Predicate Factory的父类都是RoutePredicateFactory

2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBody]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [XForwardedRemoteAddr]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
2024-08-09T11:13:00.258+08:00  INFO 17080 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]

2. 常用的内置Route Predicate使用

2.1 配置语法说明

提供了两种配置语法:

  • 快捷语法(常用):filter名称=filter值,filter值用逗号分隔
spring:
  cloud:
    gateway:
      routes:
        - id: payRoute                  
          uri: lb://payment              
          predicates:
            - Path=/pay/**              
            - Cookie=cookieKey,cookieValue  # 需同时匹配Path和Cookie,HTTP请求的Cookie的key需要为cookieKey,value需要为cookieValue
  • 全部展开语法
spring:
  cloud:
    gateway:
      routes:
        - id: payRoute                  
          uri: lb://payment              
          predicates:
            - Path=/pay/**              
            - name: Cookie  # 需同时匹配Path和Cookie,HTTP请求的Cookie的key需要为cookieKey,value需要为cookieValue
              args:
                name: cookieKey
                regexp: cookieValue

2.2 配置使用

  • After Route Predicate: 在指定时间之后发送的HTTP请求才符合要求。常用于秒杀、抢购。时间参数值可以通过System.out.println(ZonedDateTime.now())
    • 配置: - After=2024-08-09T13:28:40.332233100+08:00[Asia/Shanghai]
    • 效果: 在13:27分的时候向网关http://localhost:8088/pay/get/1发送请求报404,在13:29分的时候向网关发送请求成功
  • Before Route Predicate: 在指定时间之前发送的HTTP请求才符合要求。时间参数值可以通过System.out.println(ZonedDateTime.now())
    • 配置: - Before=2024-08-09T13:32:40.332233100+08:00[Asia/Shanghai]
    • 效果: 在13:31分的时候向网关发送请求成功,在13:33分的时候向网关http://localhost:8088/pay/get/1发送请求报404
  • Between Route Predicate: 在指定时间之间发送的HTTP请求才符合要求。时间参数值可以通过System.out.println(ZonedDateTime.now())
    • 配置: - Between=2024-08-09T13:33:40.332233100+08:00[Asia/Shanghai],2024-08-09T13:36:40.332233100+08:00[Asia/Shanghai]
    • 效果: 在13:32分的时候向网关http://localhost:8088/pay/get/1发送请求报404,在13:35分的时候向网关发送请求成功,在13:37分的时候向网关http://localhost:8088/pay/get/1发送请求报404
  • Cookie Route Predicate: 需要两个参数,一个是Cookie name ,一个是正则表达式。路由规则会通过获取对应的Cookie name值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
    • 配置: - Cookie=username,lily
    • 效果:执行curl http://localhost:8088/pay/get/1向网关发送请求报404,执行curl http://localhost:8088/pay/get/1 --cookie "username=lily"向网关发送请求成功
  • Header Route Predicate: 需要两个参数,一个是属性名称 ,一个是正则表达式。路由规则会通过获取对应的Header的属性名称和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
    • 配置: - Header=requestId, \d+。说明:请求头要有requestId属性, 并且值为整数的正则表达式
    • 效果:执行curl http://localhost:8088/pay/get/1向网关发送请求报404,执行curl http://localhost:8088/pay/get/1 -H "requestId:123456"向网关发送请求成功
  • Host Route Predicate: 接收一组参数,即一组匹配的域名列表,域名是Ant风格模式的,用逗号分隔。路由规则会通过获取对应的Header的Host的值去匹配,如果匹配上任意一个域名就会执行路由,如果没有匹配上则不执行
    • 配置: - Host=**.h1.com,**.h2.com。说明:请求头的Host匹配任意域名都可以
    • 效果:执行curl http://localhost:8088/pay/get/1 -H "Host:nb.h0.com"向网关发送请求报404,执行curl http://localhost:8088/pay/get/1 -H "Host:nb.h1.com"向网关发送请求成功,执行curl http://localhost:8088/pay/get/1 -H "Host:nb.h2.com"向网关发送请求成功
  • Path Route Predicate: 接收一组参数,即一组匹配的路径列表,路径是Ant风格模式的,用逗号分隔。路由规则会通过获取对应的path路径的值去匹配,如果匹配上任意一个路径就会执行路由,如果没有匹配上则不执行
    • 配置: - Path=/pay/get/{segment},/pay/list/**
    • 效果:向网关发送http://localhost:8088/pay/get2/1请求报404,向网关发送http://localhost:8088/pay/get/1请求成功,向网关发送http://localhost:8088/pay/list/detail/1请求成功
  • Query Route Predicate: 需要两个参数,一个是请求参数名称 ,一个是正则表达式。路由规则会通过获取对应的请求参数的名称和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
    • 配置: - Query=username, \d+。说明:请求参数要有username名称, 并且其值为整数的正则表达式
    • 效果:执行curl http://localhost:8088/pay/get/1向网关发送请求报404,执行curl http://localhost:8088/pay/get/1?username=123456"向网关发送请求成功
  • RemoteAddr Route Predicate: 接收一组参数,即一组匹配的远程地址列表,远程地址是CIDR(无类域间路由),用逗号分隔。路由规则会通过获取对应的远程地址的值去匹配,如果匹配上任意一个远程地址就会执行路由,如果没有匹配上则不执行
    • CIDR(无类域间路由):支持IPV4和IPV6, 一个形如255.255.255.255的ip地址共32位。72.108.25.1/24无类域间路由表示前24位是网络地址,则只有8位是主机地址,所以主机范围为72.108.25.072.108.25.25572.109.25.2/30无类域间路由表示前30位是网络地址,则只有2位是主机地址,所以主机范围为72.109.25.072.109.25.3
    • 配置: - RemoteAddr=72.108.25.1/24,72.109.25.2/30
    • 效果:从ip为72.107.25.8的服务器向网关发送http://10.8.12.67:8088/pay/get/1请求报404,从ip为72.108.25.18的服务器向网关发送http://10.8.12.67:8088/pay/get/1请求成功,从ip为72.109.25.3的服务器向网关发送http://10.8.12.67:8088/pay/get/1请求成功
  • Method Route Predicate: 接收一组参数,即一组匹配的请求方式列表,用逗号分隔。路由规则会通过获取对应的请求方式的值去匹配,如果匹配上任意一个请求方式就会执行路由,如果没有匹配上则不执行
    • 配置: - Method=GET,POST
    • 效果:以PUT方式向网关发送http://10.8.12.67:8088/pay/get/1请求报404,以GET方式向网关发送http://10.8.12.67:8088/pay/get/1请求成功,以POST方式向网关发送http://10.8.12.67:8088/pay/get/1请求成功

3. 自定义Route Predicate Factory

3.1 实现步骤:

  1. 在gatewayServer项目中新建自定义Predicate Factory类MyRoutePredicateFactory。类名的后缀必须是RoutePredicateFactory。所以这里创建的是一个My Route Predicate
  2. 类继承AbstractRoutePredicateFactory。也可以继承RoutePredicateFactory接口
  3. 实现无参构造器,调用父类的构造器
  4. 实现一个配置类MyRoutePredicateFactory.Config,定义需要验证的值userType
  5. 重写父类的apply方法,实现匹配userType成功和失败的逻辑
  6. 重写父类的shortcutFieldOrder方法,让其支持shortcut语法

3.2 实现代码如下:

import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;


@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{

    public MyRoutePredicateFactory()
    {
        super(MyRoutePredicateFactory.Config.class);
    }

    @Validated  // 用@validated来校验数据,如果数据异常会统一抛出异常
    public static class Config {   
        @Setter
        @Getter
        @NotEmpty
        private String userType;     // 验证用户类型
    }

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config)
    {
        return new Predicate<ServerWebExchange>()
        {
            @Override
            public boolean test(ServerWebExchange serverWebExchange)
            {
                // 获取request参数中的userType
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");

                if (userType == null) return false;

                // 如果request参数中的userType的值,和gatewayServer配置文件中配置的值相等,则符合条件
                if(userType.equals(config.getUserType())) return true;
               
                return false;
            }
        };
    }


    @Override
    public List<String> shortcutFieldOrder() {
        // 列表: [userType]
        return Collections.singletonList("userType");
    }

}

3.3 application.yml配置

全部展开语法配置如下:

            - name: My
              args:
                userType: gold

快捷语法配置: - My=gold

3.4 测试

启动gatewayServer项目,会打印如下日志,表示加载My Route Predicate成功

2024-08-09T17:58:37.861+08:00  INFO 5220 --- [gatewayServer] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [My]

向网关发送http://localhost:8088/pay/get/1请求报404,向网关发送http://localhost:8088/pay/get/1?userType=gold请求成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字货币交易所开发与智能合约交易系统

数字货币交易所作为加密经济的重要组成部分&#xff0c;为用户提供了一个安全、便捷的平台来买卖各种数字资产。随着区块链技术的发展&#xff0c;智能合约在交易所的应用日益普及&#xff0c;使得交易过程更加高效和透明。本文将探讨数字货币交易所的开发过程以及智能合约在交…

Spring源码学习:SpringMVC(2)DispatcherServlet初始化【子容器9大组件】

目录 DispatcherServlet类图HttpServletBean#initnew ServletConfigPropertyValues() FrameworkServlet#initServletBeaninitWebApplicationContextcreateWebApplicationContextconfigureAndRefreshWebApplicationContext DispatcherServlet内部9大组件初始化初识9大组件Dispat…

大模型还能产生幻觉?一文讲清楚原理和解决方法

“像我们这样相信物理学的人都知道&#xff0c;过去、现在和未来之间的区别只是一种顽固执着的幻觉。换句话说&#xff0c;时间是一种幻觉。” ——波尔 幻觉&#xff0c;即一种看似真&#xff0c;实为假的感受。最近接触到了一个概念&#xff1a;大模型幻觉。有点好奇&#…

【Qt | QList 】QList<T> 容器详细介绍和例子代码

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-09-26 …

python面向对象三大特性

面向对象 面向对象编程&#xff0c;是许多编程语言都支持的一种编程思想。 基于模板(类)去创建实体(对象)&#xff0c;使用对象去完成功能开发 面向对象的三大特性 封装继承多态 封装 封装表示&#xff1a;将现实世界事物的属性和行为&#xff0c;封装到类中&#xff0c;描…

打造高质量软件架构 - 9大质量属性

关注TechLead&#xff0c;复旦博士&#xff0c;分享云服务领域全维度开发技术。拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;复旦机器人智能实验室成员&#xff0c;国家级大学生赛事评审专家&#xff0c;发表多篇SCI核心期刊学术论文&#xff0c;阿里云认…

球体RCS计算 - 金属球的单站RCS【CST软件分析】

用金属球算RCS雷达散射截面可谓RCS的入门案例&#xff0c;本期用T和I两个求解器算单站RCS进行比较。 Step 1. RCS模板&#xff0c;T-solver&#xff0c; 频率0-5GHz&#xff0c;然后建模&#xff0c;半径10.16cm&#xff0c;可以算出来电尺寸在5GHz大概为三个波长&#xff0c;…

ROS理论与实践学习笔记——2 ROS通信机制之常用的命令

4.1 rosnode操作节点 rosnode&#xff1a;是用于获取节点信息的命令。 rosnode ping 测试到节点的连接状态 rosnode list 列出活动节点 rosnode info 打印节点信息 rosnode machine 列出指定设备上节点 rosnode kill 杀死某个节点 rosnode cleanup 清除不…

Python中的数据处理与分析:从基础到高级

在数据科学和数据分析领域&#xff0c;Python凭借其丰富的库和强大的生态系统&#xff0c;成为了最受欢迎的语言之一。本文将从基础到高级&#xff0c;详细介绍如何使用Python进行数据处理和分析&#xff0c;涵盖数据清洗、数据转换、数据可视化等多个方面。 1. 数据导入与导出…

华为 HCIP-Datacom H12-821 题库 (27)

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1. 如图&#xff0c;BGP 下有如下配置&#xff0c;下面哪些描述是错误的&#xff1f; A、Time…

Minderbinder:一款基于eBPF的进程安全测试工具

关于Minderbinder Minderbinder是一款基于eBPF的进程安全测试工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以通过注入噪声来测试目标进程的安全性。 Minderbinder 是一款使用 eBPF 将故障注入正在运行的进程的工具。当前版本的Minderbinder 可以通过将 kprobe…

动手学LLM(ch2)

2.1 理解词嵌入 深度神经网络模型&#xff0c;包括大型语言模型&#xff08;LLMs&#xff09;&#xff0c;无法直接处理原始文本&#xff0c;因为文本是分类数据&#xff0c;与神经网络的数学运算不兼容。为了达到这个目的&#xff0c;需要将单词转换为连续值向量。记住一句话…

“Y模型”—我在3年实操后的个人总结

一直想写一篇关于【需求分析】及【产品设计】方面个人最常用的一些方式方法&#xff0c;对于一些刚入行以及埋头苦干的同学来说&#xff0c;大多数情况都是粗放式凭感觉的分析产品。 因为自己也有过这样的阶段&#xff0c;深知这种思考方式的弊端。从用户场景/反馈到具象化的产…

Linux标准IO(四)-格式化I/O输入

C 库函数提供了 3 个格式化输入函数&#xff0c;包括&#xff1a;scanf()、fscanf()、sscanf()&#xff0c;其函数定义如下所示&#xff1a; #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(c…

2023年金融科技建模大赛(初赛)开箱点评,多分类模型实战

原创作者Toby&#xff0c;文章来源公众号&#xff1a;python风控模型&#xff0c;2023年金融科技建模大赛&#xff08;初赛&#xff09;开箱点评 各位同学大家好&#xff0c;我是Toby老师。2023年金融科技建模大赛&#xff08;初赛&#xff09;从今年10月14日开始&#xff0c;…

最强反推更新!Joy Caption Alpha One详细测评、在线免费使用

免费教程网站&#xff1a;AI教程_深度学习入门指南 - 站长素材 (chinaz.com) 原文链接&#xff1a;最强反推更新&#xff01;Joy Caption Alpha One详细测评、在线免费使用 (chinaz.com) JoyCaption在一周前悄悄上线了最新版本Joycaption alpha one Joycaption alpha one免费在…

Python进阶:利用NotImplemented优化你的对象交互逻辑,让Python对象间的操作更加智能与灵活

推荐阅读&#xff1a;从混乱到清晰&#xff1a;用NotImplementedError重构你的Python代码&#xff0c;NotImplementedError如何助你打造更健壮的API NotImplemented 在Python中&#xff0c;NotImplemented并不是一个异常类&#xff0c;而是一个特殊的值&#xff0c;用于在二元…

linux桌面软件(wps)内嵌到其他窗口

程序测试环境是&#xff1a;slackware系统&#xff0c;属于linux系统&#xff0c;有桌面&#xff08;Xface Session&#xff09;。系统镜像是&#xff1a;slackware64-15.0-install-dvd.iso。qt、c代码实现。 程序功能&#xff1a;将已经打开的wps&#xff08;word、pdf等都可…

【优选算法】(第五篇)

目录 ⻓度最⼩的⼦数组&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 ⽆重复字符的最⻓⼦串&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 ⻓度最⼩的⼦数组&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1a;. - …

分割数组的最大值

题目链接 分割数组的最大值 题目描述 注意点 0 < nums[i] < 10^61 < nums.length < 10001 < k < min(50, nums.length) 解答思路 首先需要理解题意&#xff0c;需要将这个数组分成 k 个非空的连续子数组&#xff0c;找到划分组合中子数组和的最大值最小…