Spring Cloud Gateway网关的高级特性之GatewayFilter Factories(路由过滤器)

news2024/9/21 22:55:03

1、GatewayFilter Factories(路由过滤器)

官方访问地址:点击这里

来自官方的解释如下图所示:
在这里插入图片描述

简单来说就是:

  • 客户端向 Spring Cloud Gateway 发送请求。
  • 如果请求与某个路由匹配,则该请求会被传递给 Gateway Web Handler。
  • Gateway Web Handler 将请求通过一系列过滤器,这些过滤器可以做一些预处理工作(比如添加头部信息、修改请求参数等)。
  • 过滤器处理完成后,实际的代理请求才会被发送到目标服务。
  • 当响应从目标服务返回时,它还会经过相同的过滤器链,这时过滤器可以做一些后处理工作(例如修改响应内容、添加响应头等)。
  • 最终处理完毕后,响应被返回给客户端。

路由过滤器的主要作用就是用来做请求鉴权、异常处理等,比较典型的就有记录接口调用时长统计。

2、 Filter过滤的类型

  1. 全局默认过滤器Global Filters:官网;gateway出厂默认已有的,直接用即可,主要作用于所有的路由不需要在配置文件中配置,作用在所有的路由上,实现GlobalFilter接口即可;
  2. 单一内置过滤器GatewayFilter: 官网;也可以称为网关过滤器,这种过滤器主要是作用于单一路由或者某个路由分组;
  3. 定义过滤器

3、 Gateway内置的过滤器

这里只演示常用的内置过滤器,其他的原理都是一样的。

3.1 The AddRequestHeader GatewayFilter Factory(指定请求头内容ByName)

我们在网关controller中编写测试接口:
Example 14. GateWayController.java

@RestController
public class GateWayController{
    @GetMapping(value = "/pay/gateway/filter")
    public ResultData<String> getGatewayFilter(HttpServletRequest request){
        String result = "";
        Enumeration<String> headers = request.getHeaderNames();
        while(headers.hasMoreElements()) {
            String headName = headers.nextElement();
            String headValue = request.getHeader(headName);
            System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
            if(headName.equalsIgnoreCase("X-Request-red")
                    || headName.equalsIgnoreCase("X-Request-my"))  {
                result = result+headName + "\t " + headValue +" ";
            }
        }
        return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
    }
}

Example 14. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue # 请求头kv,若一头含有多参则重写一行设置
        - AddRequestHeader=X-Request-my,name

重启服务,并访问http://localhost:端口号/pay/gateway/filter,查看控制台信息。

3.2 The RemoveRequestHeader GatewayFilter Factory (删除请求头ByName)

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=sec-fetch-site	# 删除请求头sec-fetch-site

注意:观察删除前后控制台打印的信息
删除前:
在这里插入图片描述
删除后:
在这里插入图片描述

3.3 The SetPath GatewayFilter Factory(修改请求头)

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - SetRequestHeader=sec-fetch-mode,Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy

修改前:
在这里插入图片描述

修改后(注意要重启服务):
在这里插入图片描述

3.4 The AddRequestParameter\RemoveRequestParameter GatewayFilter Factory(添加\删除请求参数)

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestparameter_route
        uri: https://example.org
        filters:
        - RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
        - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v

修改controller中的接口方法:

@GetMapping(value = "/pay/gateway/filter")
public ResultData<String> getGatewayFilter(HttpServletRequest request){
    String result = "";
    Enumeration<String> headers = request.getHeaderNames();
    while(headers.hasMoreElements()) {
            String headName = headers.nextElement();
            String headValue = request.getHeader(headName);
            System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
            if(headName.equalsIgnoreCase("X-Request-red")
                    || headName.equalsIgnoreCase("X-Request-my"))  {
                result = result+headName + "\t " + headValue +" ";
            }
        }

    System.out.println("=============================================");
    String customerId = request.getParameter("customerId");
    System.out.println("request Parameter customerId: "+customerId);

    String customerName = request.getParameter("customerName");
    System.out.println("request Parameter customerName: "+customerName);
    System.out.println("=============================================");

    return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
}
访问地址:
http://localhost:端口号/pay/gateway/filter 
http://localhost:端口号/pay/gateway/filter?customerld=9999&customerName=z3 

注意观察控制台打印信息。。

3.5 响应头相关的配置

  1. The AddResponseHeader GatewayFilter Factory
  2. The RemoveResponseHeader GatewayFilter Factory
  3. ** The SetRequestHeader GatewayFilter Factory**
spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue #新增响应头参数,并将X-Response-Red的值设置为Blue
        - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
        - SetResponseHeader=Date,2099-11-11 # 设置响应头Date值为2099-11-11

3.6 前缀和路径相关的配置

  1. The PrefixPath GatewayFilter Factory(自动添加路径前缀)
  2. The SetPath GatewayFilter Factory(修改访问路径)
  3. The RedirectTo GatewayFilter Factory(重定向到某个页面)
spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
      # - Path=/gateway/filter/** # 真实地址
      - Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤
      - Path=/XYZ/abc/{segment}  # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
        filters:
        - PrefixPath=/mypath	# 表示加了这个前缀胡访问的就是http://localhost:端口号/mypath/gateway/filter,,但是实际上调用的还是http://localhost:端口号/gateway/filter
        - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致
        - RedirectTo=302, http://www.baidu.com/ # 访问http://localhost:9527/gateway/filter跳转到http://www.baidu.com/

4、自定义全局Filter

需求:统计接口调用耗时情况。
通过自定义全局过滤器搞定上述需求。

自定义全局过滤器的官方地址点击这里查看

4.1 实现步骤

1、新建类MyGlobalFilter并实现GlobalFilter,Ordered两个接口

@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered{
    /**
     * 数字越小优先级越高
     * @return
     */
    @Override
    public int getOrder(){
        return 0;
    }

    private static final String BEGIN_VISIT_TIME = "begin_visit_time";//开始访问时间
    /**
     *第2版,各种统计
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //先记录下访问接口的开始时间
        exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());

        return chain.filter(exchange).then(Mono.fromRunnable(()->{
            Long beginVisitTime = exchange.getAttribute(BEGIN_VISIT_TIME);
            if (beginVisitTime != null){
                log.info("访问接口主机: " + exchange.getRequest().getURI().getHost());
                log.info("访问接口端口: " + exchange.getRequest().getURI().getPort());
                log.info("访问接口URL: " + exchange.getRequest().getURI().getPath());
                log.info("访问接口URL参数: " + exchange.getRequest().getURI().getRawQuery());
                log.info("访问接口时长: " + (System.currentTimeMillis() - beginVisitTime) + "ms");
                log.info("我是美丽分割线: ###################################################");
                System.out.println();
            }
        }));
    }
}

2、yml配置文件

server:
  port: 9527

spring:
  application:
    name: cloud-gateway #以微服务注册进consul或nacos服务列表内
  cloud:
    consul: #配置consul地址
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        service-name: ${spring.application.name}
    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            - After=2023-12-30T23:02:39.079979400+08:00[Asia/Shanghai]

        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由,默认正确地址
          filters:
            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置

3、测试
浏览器访问:

  • http://localhost:9527/pay/gateway/info
  • http://localhost:9527/pay/gateway/get/1
  • http://localhost:9527/pay/gateway/filter
    http://localhost:9527/pay/gateway/info
    请注意,上述示例代码仅供参考,你可能需要根据你的项目需求和实际情况进行适当的调整。

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

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

相关文章

OpenEuler安装部署教程

目录 OpenEuler安装部署教程 MobaXterm一款全能的远程工具 yum安装软件 vim编辑器&#xff08;了解&#xff09; 防火墙 常用命令 网络工具netstat & telnet 进程管理工具top ps 磁盘free、fdisk 用户、组&#xff08;了解&#xff09; 权限&#xff08;了解&am…

实验3-9 三天打鱼两天晒网

//实验3-9 三天打鱼两天晒网/* 中国有句俗语叫“三天打鱼两天晒网”。 假设某人从某天起&#xff0c;开始“三天打鱼两天晒网”&#xff0c; 问这个人在以后的第N天中是“打鱼”还是“晒网”&#xff1f; */#include<stdio.h> #include<math.h> int main(){int n; …

Photoshop的下载和安装教程

找到Adobe 的官网 https://www.adobe.com/cn/ 创建一个新的账户,如果你没有账户的话 后面安装步骤来注册 下载和安装 登录之后 点击 点击 点击 然后进行下载和安装 然后就是漫长的等待 安装完成 点击 这只是一个安装Photoshop的教程,也可以根据别人的安装包来进行安装

ThreadPoolExecutor工作原理及源码详解

一、前言 创建一个线程可以通过继承Thread类或实现Runnable接口来实现&#xff0c;这两种方式创建的线程在运行结束后会被虚拟机回收并销毁。若线程数量过多&#xff0c;频繁的创建和销毁线程会浪费资源&#xff0c;降低效率。而线程池的引入就很好解决了上述问题&#xff0c;…

万字详解 MapStruct Plus,带你快速上手!

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 前言一、为什么要用 MapStruct&#xff08;背景&#xff09;二、MapStruct Plus 的快速开始1. 引入依赖2. 指定对象映射关系3. 编写测试代码4. 运行结果5. 原理解析 三、自定义实体类中的属性转换1. 自定义一个类型…

【IO】使用父子进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,子进程结束后退出,父进程回收子进程的资源

1、使用父子进程完成两个文件的拷贝&#xff0c;父进程拷贝前一半内容&#xff0c;子进程拷贝后一半内容&#xff0c;子进程结束后退出&#xff0c;父进程回收子进程的资源 #include <myhead.h>int main(int argc, const char *argv[]) {//判断输入的格式是否符合要求i…

预测性维护:一种基于因果技术语言处理 (CTLP) 的智能故障诊断方法

关键词&#xff1a;预测性维护、因果贝叶斯网络、ROX数据 在工业运营和维护领域&#xff0c;资产绩效最大化和风险最小化至关重要。随着工业设备组件的磨损和恶化&#xff0c;系统会表现出一系列变化&#xff0c;这些变化的严重程度会逐渐增加&#xff0c;直到最终发生故障。在…

C++_string_知识总结(初学)

基础认识&#xff1a; string严格意义上不属于STL容器&#xff0c;其出现的时间早于STL&#xff0c;这也导致了string官方库中部分函数冗余。但是这也体现了语言发展中的一个重要现象——向前兼容。和很多STL容器一样&#xff0c;string是一个类&#xff0c;核心是一个顺序表&…

MySQL:GROUP BY 分组查询

分组查询是SQL中一个非常强大的功能&#xff0c;它允许我们将数据按照一个或多个字段进行分组&#xff0c;并对每个分组进行聚合计算&#xff08;如求和、平均值、最大值、最小值等&#xff09;。在MySQL中&#xff0c;我们使用 GROUP BY 关键字来实现分组查询。 核心语法 SE…

笑出腹肌的饼图绘制秘籍:Matplotlib让你秒变数据烘焙大师!

1. 引言 亲们&#xff0c;还在为数据报告里的饼图头疼吗&#xff1f;别怕&#xff0c;Matplotlib来救场啦&#xff01;它不只是个绘图工具&#xff0c;简直是数据界的魔术师&#xff0c;让你的饼图既专业又有趣。跟我学几招&#xff0c;保证让你的观众边吃边看&#xff0c;爱不…

Linux驱动开发—编写第一个最简单的驱动模块

文章目录 开发驱动准备工作1.正常运行的Linux系统的开发板2.内核源码树3.nfs挂载的rootfs4.得心趁手的IDE 第一个Hello world 驱动程序常见模块的操作命令模块的初始化和清理模块的版本信息模块中的各种宏 示例Hello World代码printk函数解析 使用MakeFile编译驱动模块使用insm…

谷歌账号异常,成功通过验证后这个界面操作指引:建议增加辅助手机和邮箱

许多朋友对下面这个界面都很熟悉&#xff0c;通常是账号被停用后的时候输入账号和密码后&#xff0c;还需要再次输入手机号码验证。而且这个时候输入国内的号码或者谷歌账号绑定的辅助手机号码都不管用&#xff0c;提示此电话号码用于验证的次数过多&#xff0c;或者此电话号码…

链表篇:03-合并有序链表

解题思路&#xff1a; 使用双指针&#xff0c;一个指针指向头节点&#xff0c;然后另外一个指针进行移动。让其头节点保持不动&#xff0c;最后循环遍历两个链表&#xff0c;将其挂到头指针所在的节点上。 temp 守卫节点&#xff0c;用于指向头节点&#xff0c;防止头节点丢…

机械学习—零基础学习日志(高数17——极限局部有界性)

零基础为了学人工智能&#xff0c;真的开始复习高数 这里我们更加详细讲解函数极限性质。上一篇文章里有一些内容还需要进一步补充。 局部有界性 这里是局部有界性的需要注意的事项。第3点&#xff0c;如果函数在闭区间内连续&#xff0c;则必定有界。试想一下&#xff0c;如…

Log4j2漏洞

Log4j2漏洞 步骤一:执行以下命令启动靶场环境并在浏览器访问!!! systemctl start docker cd vulhub/log4j/CVE-2021-44228 vi docker-compose.yml //编写docker-compose.xml的端口和版本号 docker-compose up -d # 访问网址 http://192.168.30.131:8983/solr/#/步骤二:先在自…

MyBatis入门如何使用操作数据库及常见错误(yml配置)

一&#xff0c;什么是MyBatis 是一款优秀的持久层框架&#xff0c;用于简化jdbc的开发 持久层&#xff1a;指的就是持久化操作的层&#xff0c;通常也就是数据访问层&#xff08;dao&#xff09;&#xff0c;也就是用来操作数据库。 也就是MyBatis是让你更加简单完成程序与数…

ECCV 2024前沿科技速递:GLARE-基于生成潜在特征的码本检索点亮低光世界,低光环境也能拍出明亮大片!

在计算机视觉与图像处理领域&#xff0c;低光照条件下的图像增强一直是一个极具挑战性的难题。暗淡的光线不仅限制了图像的细节表现&#xff0c;还常常引入噪声和失真&#xff0c;极大地影响了图像的质量和可用性。然而&#xff0c;随着ECCV 2024&#xff08;欧洲计算机视觉会议…

form表单按钮根据编辑/只读状态显示和隐藏

1. 场景阐述: form表单自定义按钮,在编辑模式显示,在只读模式隐藏 2. 效果: 这里的保存按钮是自定义按钮,在编辑状态的时候显示,非编辑状态下隐藏 3. 解决方案: 如下所示,只需要在按钮中添加odoo自带class类oe_edit_only即可 <header><button type"object"…

桌面管理利器:2024年度待办事项工具评选

国内外主流的10款待办事项桌面工具对比&#xff1a;PingCode、Worktile、滴答清单、番茄ToDo、Teambition、Tower、有道云笔记、TickTick、Any.do、Trello。 在忙碌的工作日中&#xff0c;管理日常任务和待办事项常常让人感到不胜其烦。选择合适的待办事项桌面工具&#xff0c;…

【Python实战因果推断】67_图因果模型2

目录 Are Consultants Worth It? Crash Course in Graphical Models Chains Are Consultants Worth It? 为了展示有向无环图(DAG)的力量&#xff0c;让我们考虑一个更有趣但处理因素并未随机化的情况。假设你是某公司的经理&#xff0c;正在考虑是否聘请顶级咨询顾问。你…