Spring Cloud Gateway中断言路由和过滤器的使用

news2025/3/13 7:43:27

 一,Gateway概念

Spring Cloud Gateway(简称 Gateway)是一个基于 Spring WebFlux 的 API 网关解决方案,旨在为微服务架构中的客户端提供路由、负载均衡、认证、限流、监控等功能。它作为微服务架构中的流量入口,通常位于客户端和后端微服务之间,处理来自客户端的请求并将其路由到相应的服务。

主要特性

  1. 路由功能:Spring Cloud Gateway 可以根据请求的不同特征(如路径、方法、头部、参数等)将请求路由到不同的微服务。
  2. 负载均衡:支持与服务注册中心(如 Eureka)集成,能够将流量分发到多个实例,以实现负载均衡。
  3. 过滤器:提供了丰富的过滤器功能,可以在请求和响应的生命周期中进行定制化处理。例如,身份认证、日志记录、限流等。
  4. 反向代理:可以将请求转发给后端服务,实现反向代理功能。
  5. 高可用和可扩展性:通过与 Spring Cloud 配合使用,Spring Cloud Gateway 能够在微服务架构中提供高可用和扩展性支持。
  6. 监控:可以与 Spring Boot Actuator 集成,提供请求和响应的监控功能,帮助开发人员监控系统的健康状况和性能。

二,基本路由

        路由是将客户端请求发送到后端服务的主要组件。它定义了请求的匹配规则以及请求将被转发到的目标(即URI)。每个路由都具有一个iduri以及predicates

  • id:每个路由的唯一标识符。
  • uri:路由转发的目标URI。对于lb://协议,它指向服务注册中心(如Eureka)中的服务,表示请求将被转发到注册的服务。
  • predicates:定义了路由的匹配条件,决定哪些请求将被此路由处理。
spring:
    cloud:
        gateway:
            routes:
                - id: order-route
                  uri: lb://service-order
                  predicates:
                    - Path=/api/order/**

三,断言

        断言(Predicates) 用于根据请求的各种属性来匹配路由,它们是路由的核心部分。断言支持不同的匹配条件,如路径、请求方法、请求头等。通过不同的请求模式来匹配对应的微服务。

3.1在Spring Cloud Gateway的配置中,断言有两种写法:

  • 长写法:指定完整的断言语法,明确标明断言的类型。
spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          uri: lb://service-order
          predicates:
            - name: Path
              args:
                pattern: /api/order/**
  • 短写法:是断言的简化写法,直接使用断言类型的简洁形式。
spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          uri: lb://service-order
          predicates:
            - Path=/api/order/**

系统内置断言(Predicates)

Spring Cloud Gateway 提供了很多内置的断言类型,用来处理各种请求匹配需求。常用的断言类型包括:

        这张图展示了Spring Cloud Gateway中常用的路由断言(Predicates)及其相关参数说明。断言是路由配置的重要组成部分,它们用来判断请求是否满足特定条件,以决定是否将请求转发到目标服务。每种断言都允许通过指定参数来对请求进行详细匹配。 

3.2自定义断言

我们通过继承 AbstractRoutePredicateFactory 类,创建了一个名为 VipRoutePredicateFactory 的类,实现了自定义的路由断言逻辑,示例代码如下:

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.apache.commons.lang3.StringUtils;

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

/**
 * 自定义路由断言工厂
 */
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {

    public VipRoutePredicateFactory() {
        super(Config.class);  // 传入Config类
    }

    @Override
    public List<String> shortcutFieldOrder() {
        // 返回配置类中的字段顺序
        return Arrays.asList("param", "value");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {

            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                // 获取请求
                ServerHttpRequest request = serverWebExchange.getRequest();

                // 从请求的查询参数中获取 'param' 对应的值
                String first = request.getQueryParams().getFirst(config.param);

                // 比较查询参数的值与配置中的 'value' 是否匹配
                return StringUtils.isNotBlank(first) && first.equals(config.value);
            }
        };
    }

    // 配置类
    public static class Config {
        private String param;  // 查询参数名称
        private String value;  // 查询参数期望的值

        // Getter和Setter方法
        public String getParam() {
            return param;
        }

        public void setParam(String param) {
            this.param = param;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}
VipRoutePredicateFactory
  • 该类继承自 AbstractRoutePredicateFactory,实现了自定义断言工厂的功能。AbstractRoutePredicateFactory 是 Spring Cloud Gateway 提供的基础类,用于创建自定义的路由断言。我们将 Config.class 作为构造函数的参数传递给父类,表示我们会用 Config 类来存储断言所需的配置参数。

shortcutFieldOrder() 方法
  • 这个方法返回一个 List<String>,用于定义配置类中字段的顺序。在这个例子中,paramvalue 的顺序决定了用户在配置时,paramvalue 应该以这个顺序出现。Spring Cloud Gateway 使用 shortcutFieldOrder() 方法来生成简洁的 YAML 配置。

spring:
  cloud:
    gateway:
      routes:
        - id: vip-route
          uri: https://example.com
          predicates:
            - name: Vip(RoutePredicateFactory)//vip是断言工厂名前缀
              args:
                param: q
                value: test

apply(Config config) 方法

  • 这个方法用于应用自定义断言的逻辑,接收 Config 类的实例作为参数。Config 类包含了路由断言所需的参数(paramvalue)。该方法返回一个 Predicate<ServerWebExchange>,用于对每个请求进行断言判断。

这里的 Predicate<ServerWebExchange> 表示一个函数,它接收一个 ServerWebExchange(表示当前请求),并返回一个布尔值,表示该请求是否匹配该断言。

 test(ServerWebExchange serverWebExchange) 方法

  • 在这个方法中,我们实际执行请求的匹配逻辑。首先通过 serverWebExchange.getRequest() 获取当前请求对象。接着,我们从请求的查询参数中获取与 config.param 对应的值,存储在 first 变量中。

  • 然后,我们检查 first 是否为空,并与 config.value 进行比较。如果它们相等,并且查询参数不为空,我们返回 true,表示路由匹配成功;否则返回 false,表示路由不匹配。

 Config

  • Config 类是一个静态类,用来存储自定义断言需要的配置参数。这里有两个字段:param 表示查询参数的名称,value 表示查询参数的期望值。用户通过配置文件传入这两个参数。

  • Config 类的作用是封装从配置文件中读取的参数,并通过 @Validated 等注解进行验证

四,过滤器

        过滤器(Filters) 是用于在请求和响应过程中执行特定操作的机制。它们是在路由决策之前或之后执行的,可以对请求进行修改(如添加头部、修改请求体)或响应进行处理(如修改响应内容、记录日志等)。过滤器的使用大致可以分为两种类型:前置过滤器(pre-filter)和后置过滤器(post-filter)。前置过滤器在请求到达目标服务之前执行,后置过滤器则在响应返回客户端之前执行。过滤器主要用于以下目的:
  • 请求和响应的修改。
  • 安全性(如身份验证)。
  • 负载均衡和限流。
  • 请求日志和性能监控。

4.1基本的过滤器使用步骤:

添加依赖: 需要在pom.xml文件中加入Spring Cloud Gateway的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

创建过滤器: 可以通过实现GatewayFilter接口来创建自定义过滤器。Spring Cloud Gateway提供了GatewayFilter接口和GlobalFilter接口,分别用于处理特定路由和全局的请求过滤。

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyCustomFilter implements GatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 在请求处理之前执行的逻辑
        System.out.println("请求被过滤: " + exchange.getRequest().getURI());

        // 执行后续过滤器链
        return chain.filter(exchange);
    }
}

注册过滤器: 自定义过滤器可以通过注入GatewayFilter的方式注册到Spring的上下文中。可以将过滤器注入到@Configuration中,或者直接使用@Component注解让其自动注册。

配置路由过滤器: 在路由配置中,可以为某个特定的路由设置过滤器。

spring:
  cloud:
    gateway:
      routes:
        - id: my_route
          uri: http://httpbin.org:80
          predicates:
            - Path=/get
          filters:
            - name: RequestHeaderToRequestUri
              args:
                name: X-Request-Id

4.2全局过滤器使用步骤:

全局过滤器是应用于所有路由请求的过滤器,它们在请求到达目标服务之前和响应返回时都会被执行。全局过滤器对于记录日志、身份验证等场景非常有用。 

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


@Component
public class LoggingGlobalFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求的URL
        String path = exchange.getRequest().getURI().getPath();
        System.out.println("Request Path: " + path);
        
        // 继续处理链中的下一个过滤器
        return chain.filter(exchange);
    }
}

4.3自定义过滤器使用步骤:

Spring Cloud Gateway允许开发者创建自定义过滤器。自定义过滤器有两种类型:

  • GatewayFilter:只能作用于单个路由。
  • GlobalFilter:作用于所有路由。


import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.HttpStatus;
import reactor.core.publisher.Mono;

@Component
public class LoggingGlobalFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求的路径
        String path = exchange.getRequest().getURI().getPath();

        // 记录请求的路径
        System.out.println("Request Path: " + path);

        // 向请求中添加一个自定义的请求头
        exchange.getRequest().mutate()
                .header("X-Request-ID", "Request-" + System.currentTimeMillis())  // 设置一个自定义请求头
                .build();

        // 继续处理请求
        return chain.filter(exchange)
                .doOnTerminate(() -> {
                    // 记录响应结束时的日志
                    System.out.println("Request " + path + " processed.");
                });
    }
}
  • LoggingGlobalFilter 实现了 GlobalFilter 接口

    • 该过滤器会应用于所有的请求,不管是哪个路由请求都会执行这个过滤器的逻辑。
  • filter() 方法

    • 在这个方法中,首先我们通过 exchange.getRequest().getURI().getPath() 获取当前请求的路径。
    • 然后,我们通过 System.out.println() 打印日志,记录下请求的路径。
    • 接着,我们使用 mutate() 方法修改请求,添加了一个自定义的请求头 X-Request-ID,其值为当前时间戳(这样可以在日志中唯一标识每个请求)。
    • 最后,通过 chain.filter(exchange) 将请求继续传递给下一个过滤器链

4.4过滤器的执行顺序

Spring Cloud Gateway的过滤器按以下顺序执行:

  • 请求过滤器:请求从客户端进入网关后,过滤器链会逐个执行请求过滤器。
    • 过滤器执行顺序是链式的:GlobalFilter -> GatewayFilter
  • 响应过滤器:请求被转发到目标服务,响应返回时,再次按链式执行响应过滤器。

4.5常用过滤器

Spring Cloud Gateway提供了一些内置的过滤器,可以直接使用。例如:

  • AddRequestHeader:添加请求头部。
  • AddResponseHeader:添加响应头部。
  • RemoveRequestHeader:删除请求头部。
  • RemoveResponseHeader:删除响应头部。
  • SetPath:修改请求路径。
  • RewritePath:重写路径。
添加请求头的过滤器举例:
spring:
  cloud:
    gateway:
      routes:
        - id: add-header-route
          uri: http://localhost:8081
          predicates:
            - Path=/add-header/**
          filters:
            - AddRequestHeader=X-Custom-Header, Value

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

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

相关文章

AcWing 798. 差分矩阵

题目来源&#xff1a; 找不到页面 - AcWing 题目内容&#xff1a; 输入一个 n 行 m 列的整数矩阵&#xff0c;再输入 q 个操作&#xff0c;每个操作包含五个整数 x1,y1,x2,y2,c&#xff0c;其中 (x1,y1) 和 (x2,y2)表示一个子矩阵的左上角坐标和右下角坐标。 每个操作都要将…

Docker 部署 MySQL 8 详细图文教程

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

【Python】模式匹配 match语句详解(仅在Python 3.10及以上版本中可用)

文章目录 模式匹配 match语句(仅在 Python 3.10及以上版本 中可用)1. 基本语法2. 基本匹配操作2.1 匹配常量2.2 匹配变量2.3 匹配元组2.4 匹配列表2.5 匹配字典2.6 条件匹配 3. 应用场景 模式匹配 match语句(仅在 Python 3.10及以上版本 中可用) Python 3.10 及以上版本中才引…

算法与数据结构(最小栈)

题目 思路 为了返回栈中的最小元素&#xff0c;我们需要额外维护一个辅助栈 min_stack&#xff0c;它的作用是记录当前栈中的最小值。 min_stack的作用&#xff1a; min_stack的栈顶元素始终是当前栈 st 中的最小值。 每当st中压入一个新元素时&#xff0c;如果这个元素小于等…

openCV中如何实现滤波

图像滤波用于去除噪声和图像平滑&#xff0c;OpenCV 提供了多种滤波器&#xff1a; 1.1. 均值滤波&#xff1a; import cv2# 读取图像 image cv2.imread("example.jpg")# 均值滤波 blurred_image cv2.blur(image, (5, 5)) # (5, 5) 是滤波核的大小 滤波核大小的…

2025 BabitMF 第一期开源有奖活动正式开启 !

为了促进开源社区的交流与成长&#xff0c;字节跳动开源的多媒体处理框架 BabitMF &#xff08;GitHub - BabitMF/bmf: Cross-platform, customizable multimedia/video processing framework. With strong GPU acceleration, heterogeneous design, multi-language support, e…

Docker 安装和配置 Nginx 详细图文教程

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

链表和list

链表和list ‍ ​ ​ ​ ​ ​ ​ ​ ​ ​ 算法题中的经典操作&#xff1a;用空间代替时间​ ​ ​ ​ 双链表头插顺序&#xff1a; 1.先修改新结点的左右指针 2.然后修改结点y的左指针 3.最后修改哨兵位的右指针 双链表在任意位置&#xff08;p&#xff09;之后插入…

深度学习机器学习:常用激活函数(activation function)详解

目录 Sigmoid Function ReLU&#xff08;Rectified Linear Unit&#xff09; LeakyReLU&#xff08;Leaky Rectified Linear Unit&#xff09; ClippedReLU&#xff08;Clipped Rectified Linear Unit&#xff09; PRelu&#xff08;Parametric ReLU&#xff09; Tanh&am…

AIGC图生视频保姆级教程

一、AI文生图高阶技巧 推荐工具 ▸ MidJourney&#xff08;艺术感最强&#xff09; ▸ DALLE 3&#xff08;与ChatGPT深度联动&#xff09; ▸ Leonardo.ai&#xff08;精细化参数控制&#xff09; 核心策略 提示词架构&#xff1a; [主体描述][环境氛围][镜头语言][风格参数…

下载安装运行测试开源vision-language-action(VLA)模型OpenVLA

1. 安装 项目官网OpenVLA 首先按照官网提示的以下代码&#xff0c;执行创建环境->安装最小依赖->git克隆项目等 # Create and activate conda environment conda create -n openvla python3.10 -y conda activate openvla# Install PyTorch. Below is a sample comma…

【Zookeeper如何实现分布式锁?】

Zookeeper如何实现分布式锁? 一、ZooKeeper分布式锁的实现原理二、ZooKeeper分布式锁的实现流程三、示例代码四、总结一、ZooKeeper分布式锁的实现原理 ZooKeeper是一个开源的分布式协调服务,它提供了一个分布式文件系统的接口,可以用来存储和管理分布式系统的配置信息。 …

【MySQL】环境变量配置

环境变量英文名SystemRoot&#xff0c;直译为“系统总&#xff08;根&#xff09;目录"&#xff0c;主要指明操作系统的重要目录在哪里。那么配置MySQL的环境变量&#xff0c;就是在程序运行时&#xff0c;告诉操作系统你的MySQL目录位置。 复制MySQL安装目录&#xff1a;…

为AI聊天工具添加一个知识系统 之103 详细设计之44 自性三藏 之4 祖传代码 之2

本文要点 要点 前面的所有讨论都是为了给出我的设计项目&#xff08;为使用AI聊天工具的聊天者 开挂一个知识系统&#xff09; 的祖传代码 的完整设计&#xff0c;其中 的“槽”&#xff08;占位符变量&#xff09;的 库元&#xff08;宝性和自性creator -本俱 替换内容标准模…

假面与演员:到底是接口在使用类,还是类在使用接口?编程接口与物理接口的区别又是什么?

前言&#xff1a;本篇文章解释了接口学习过程中的2个常见问题&#xff0c;一个是“为什么是类在使用接口”&#xff0c;另一个一个是“编程接口与物理接口的差异源于所处的抽象层次和交互模式的不同”&#xff0c;旨在揭示编程接口的本质。 Part1.是类在使用接口 当学习接口时…

C# 添加图标

一、前言 为应用程序添加图标是优化用户界面、提升应用辨识度的重要操作。合适的图标能帮助用户快速识别和区分不同应用&#xff0c;增强应用的易用性和专业性。 本指南旨在为你提供详细、易懂的步骤&#xff0c;教你如何为应用程序的窗体添加图标。从图标素材的获取到具体的…

Docker 入门与实战:从安装到容器管理的完整指南

&#x1f680; Docker 入门与实战&#xff1a;从安装到容器管理的完整指南 &#x1f31f; &#x1f4d6; 简介 在现代软件开发中&#xff0c;容器化技术已经成为不可或缺的一部分。而 Docker 作为容器化领域的领头羊&#xff0c;以其轻量级、高效和跨平台的特性&#xff0c;深…

HCIA项目实践---ACL访问控制列表相关知识和配置过程

十 ACL访问控制列表 1 策略的概念 在网络连通之后&#xff0c; 把所有为了追求控制而实现的技术都叫策略 2 访问控制 在路由器流量流入或者流出的接口上&#xff0c;匹配流量&#xff0c;执行相应的动作。&#xff08;流量流入或者流出的接口并不是一个固定的概念而是一个相对的…

细说STM32F407单片机RTC入侵检测和时间戳的原理及使用方法

目录 一、入侵检测的功能 二、示例功能 三、项目设置 1、晶振、DEBUG、CodeGenerator、USART6、KEYLED 2、RTC &#xff08;1&#xff09;设置RTC的模式。 &#xff08;2&#xff09;General、Time、Date\Wake Up分组 &#xff08;3&#xff09;Tamper分组 1&#xff…

搜狗浏览器卸载教程

需求背景 今天发现geek居然无法卸载搜狗浏览器&#xff0c;作为一个老司机&#xff0c;这是不允许的。如果你使用geek或者windows的卸载&#xff0c;或者直接在它的安装包的Uninstall.exe中卸载&#xff0c;他走到100%就一直不动了。那玩意是假的。 卸载教程 结束 -----华丽的…