07-SpringCloud-Gateway新一代网关

news2024/11/26 1:06:06

一、概述

1、Gateway介绍

官网:https://spring.io/projects/spring-cloud-gateway

Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。 Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,从而加强安全保护。Spring Cloud Gateway本身也是一个微服务,需要注册进服务注册中心。

作用:

  • 反向代理
  • 鉴权
  • 流量监控
  • 熔断
  • 日志监控

在这里插入图片描述

在这里插入图片描述

2、Gateway三大核心

  • Route(路由):路由是构建网关的基本模块,它由ID,目标URL,一系列的断言和过滤器组成,如果断言为true则匹配该路由;
  • Predicate(断言):(java.util.function.Predicate)开发人员可以匹配HTTP请求中的所有内容(请求头和请求体),如果请求与断言相匹配则进行路由;
  • Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后进行修改。

在这里插入图片描述

web前端请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

predicate就是我们的匹配条件;

filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。

3、Gateway工作流程

核心逻辑:路由转发+断言判断+执行过滤链

在这里插入图片描述

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(Pre)或之后(Post)执行业务逻辑。

在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;

在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

二、入门配置

1、建Module

新建 cloud-gateway9527 模块

在这里插入图片描述

2、改POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu.cloud</groupId>
        <artifactId>cloud2024</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>cloud-gateway9527</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--服务注册发现consul discovery,网关也要注册进服务注册中心统一管控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- 指标监控健康检查的actuator,网关是响应式编程删除掉spring-boot-starter-web dependency-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3、写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}

4、主启动

package com.atguigu.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient //服务注册与发现
public class Main9527 {
    public static void main(String[] args) {
        SpringApplication.run(Main9527.class, args);
    }
}

5、测试

在这里插入图片描述

三、路由映射

不暴露8001端口,希望在8001真正的支付微服务外面套一层9527网关

1、改造8001模块

新建PayGateWayController

package com.atguigu.cloud.controller;

import cn.hutool.core.util.IdUtil;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.service.PayService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName PayGateWayController
 * @Author link
 * @Date: 2024/11/6 下午3:56
 * @Version v1.0
 * @Description:
 */
@RestController
public class PayGateWayController {
    @Resource
    PayService payService;

    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData<Pay> getById(@PathVariable("id") Integer id)
    {
        Pay pay = payService.getById(id);
        return ResultData.success(pay);
    }

    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
    }
}

2、9527模块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: http://localhost:8001                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


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

3、修改公共api模块

package com.atguigu.cloud.apis;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.entities.PayDTO;
import com.atguigu.cloud.resp.ResultData;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @ClassName PayFeignApi
 * @description: 通用api
 * @author: linkai
 * @create: 2024-11-03 15:29
 **/
@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {

    @PostMapping(value = "/pay/add")
    @Operation(summary = "新增",description = "新增支付流水方法")
    public ResultData addPay(@org.springframework.web.bind.annotation.RequestBody PayDTO payDTO);

    @DeleteMapping(value = "/pay/del/{id}")
    @Operation(summary = "删除",description = "删除支付流水方法")
    public  ResultData deletePay(@PathVariable("id") Integer id);
    @PutMapping(value = "/pay/update")
    @Operation(summary = "修改",description = "修改支付流水方法")
    public ResultData updatePay(@RequestBody PayDTO payDTO);
    @GetMapping(value = "/pay/get/{id}")
    @Operation(summary = "查询",description = "根据id查询支付流水方法")
    public ResultData getPayById(@PathVariable("id") Integer id);

    @GetMapping(value = "/pay/getPayList")
    @Operation(summary = "查询全部",description = "查询全部支付流水方法")
    public ResultData getPayList();

    /**
     * openfeign天然支持负载均衡演示
     * @return
     */
    @GetMapping(value = "/pay/get/info")
    public String getInfoByConsul();


    /***
     * Resilience4j CircuitBreaker 的例子
     **/
    @GetMapping(value = "/pay/circuit/{id}")
    public String myCircuit(@PathVariable("id") Integer id);
    /***
     * Resilience4j Bulkhead  的例子
     **/
    @GetMapping(value = "/pay/bulkhead/{id}")
    public String myBulkhead(@PathVariable("id") Integer id);
    /***
     * Resilience4j Ratelimit  的例子
     **/
    @GetMapping(value = "/pay/ratelimit/{id}")
    public String myRatelimit(@PathVariable("id") Integer id);
    /***
     * Micrometer 链路追踪 的例子
     **/
    @GetMapping(value = "/pay/micrometer/{id}")
    public String myMicrometer(@PathVariable("id") Integer id);

    /**
     * Gateway 网关
     **/
    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData getById(@PathVariable("id") Integer id);

    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo();

}



4、修改feign-order80模块

新建OrderGateWayController

package com.atguigu.cloud.controller;

import com.atguigu.cloud.apis.PayFeignApi;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.resp.ResultData;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName OrderGateWayController
 * @Author link
 * @Date: 2024/11/6 下午4:10
 * @Version v1.0
 * @Description:
 */
@RestController
public class OrderGateWayController {
    @Resource
    private PayFeignApi payFeignApi;

    @GetMapping(value = "/feign/pay/gateway/get/{id}")
    public ResultData getById(@PathVariable("id") Integer id)
    {
        return payFeignApi.getById(id);
    }

    @GetMapping(value = "/feign/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return payFeignApi.getGatewayInfo();
    }
}

5、测试

测试一:8001和9527访问

在这里插入图片描述

测试二:启动订单80服务,用80访问

在这里插入图片描述

但是这时候我们停掉网关也是一样可以访问,这是因为我们在PayFeignApi中定义通过找8001这个服务,需要改成网关服务

在这里插入图片描述

现在我们停掉网关:

在这里插入图片描述

开启网关:

在这里插入图片描述

四、Gateway高级特性

1、Route以微服务名-动态获取微服务URL

把uri的ip地址改成服务名称,如uri: lb: //cloud-payment-service

修改后的yml

xmserver:
  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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


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

这样之后我们修改8001服务的端口,也不会受到影响

在这里插入图片描述

2、Predicate断言(谓语)

配置方式两种:

快捷方式配置

快捷方式配置由过滤器名称识别,后跟等号(=),后跟用逗号分隔的参数值(,)。

应用程序.yml

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue

前面的示例定义了CookieRoute Predicate Factory,它有两个参数:cookie 名称mycookie和要匹配的值mycookievalue

充分展开配置

完全展开的参数看起来更像带有名称/值对的标准 yaml 配置。通常,会有一个name键和一个args键。args键是用于配置谓词或过滤器的键值对的映射。

应用程序.yml

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
            regexp: mycookievalue
1)常用的内置Route Predicate(2024.11月份最新 4.1.5版本)

以http://localhost:9527/pay/gateway/get/1地址为例,测试断言

1:After Request Predicate(请求后断言)

路由After谓词工厂采用一个参数 a datetime(即 java ZonedDateTime)。此谓词匹配在指定日期时间之后发生的请求。以下示例配置了 after 路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: after_route
          uri: https://example.org
          predicates:
          - After=2017-01-20T17:42:47.789-07:00[America/Denver]

获得ZonedDateTime示例:

package com.atguigu.cloud.util;

import java.time.ZonedDateTime;

/**
 * @ClassName CreateZoneDateTime
 * @Author link
 * @Date: 2024/11/7 上午8:51
 * @Version v1.0
 * @Description:
 */
public class CreateZoneDateTime {
    public static void main(String[] args) {

        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);
    }
}

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
             - After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
            #- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
2:Before Request Predicate(请求前断言)

路由Before谓词工厂接受一个参数 a datetime(即 java ZonedDateTime)。此谓词匹配在指定 之前发生的请求datetime。以下示例配置了一个 before 路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: before_route
          uri: https://example.org
          predicates:
          - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
            #- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
3:Between Request Predicate(两者之间断言)

路由Between谓词工厂接受两个参数,datetime1和,datetime2 它们是 JavaZonedDateTime对象。此谓词匹配发生在 之后datetime1和 之前的请求datetime2datetime2参数必须是 之后datetime1。以下示例配置了一个 之间 路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: between_route
          uri: https://example.org
          predicates:
          - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
            #- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
4:Cookie Request Predicate(Cookie请求断言)

路由Cookie谓词工厂采用两个参数,cookiename和 a regexp(Java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置 cookie 路由谓词工厂:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: cookie_route
          uri: https://example.org
          predicates:
          - Cookie=chocolate, ch.p

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
             - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
             - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由

        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
5:Header Request Predicate(标头请求断言)

路由Header谓词工厂采用两个参数,即header和 a regexp(Java 正则表达式)。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。以下示例配置标头路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: header_route
          uri: https://example.org
          predicates:
          - Header=X-Request-Id, \d+

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
             - Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
             - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由

        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
6:Host Request Predicate(主机请求断言)

路由Host谓词工厂采用一个参数:主机名列表patterns。该模式是 Ant 样式的模式,以.作为分隔符。此谓词匹配与Host模式匹配的标头。以下示例配置主机路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: host_route
          uri: https://example.org
          predicates:
          - Host=**.somehost.org,**.anotherhost.org

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由

        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
7:Method Request Predicate(方法请求断言)

请求谓词Method接受methods一个或多个参数:要匹配的 HTTP 方法。以下示例配置方法路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: method_route
          uri: https://example.org
          predicates:
          - Method=GET,POST

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由

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

Request PathPredicate 接受两个参数:一个 Spring 列表PathPattern patterns。此 Request Predicate 使用RequestPredicates.path()作为底层实现。以下示例配置路径路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: path_route
          uri: https://example.org
          predicates:
          - Path=/red/{segment},/blue/{segment}

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
9:Query Request Predicate(查询请求断言)

路由Query谓词工厂采用两个参数:一个必需参数param和一个可选参数regexp(Java 正则表达式)。以下示例配置查询路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: query_route
          uri: https://example.org
          predicates:
          - Query=green

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Query=username, \d+
            #- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
10:Weight Request Predicate(权重请求断言)

路由Weight谓词工厂采用两个参数:groupweight(一个int)。权重按组计算。以下示例配置权重路由谓词:

应用程序.yml

spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: weight_high
          uri: https://weighthigh.org
          predicates:
          - Weight=group1, 8
        - id: weight_low
          uri: https://weightlow.org
          predicates:
          - Weight=group1, 2

该路由将把80%的流量转发到weightthigh.org,20%的流量转发到weightlow.org。

修改9527YML

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Weight=group1, 2
            #- Query=username, \d+
            #- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - Weight=group1, 8
            #- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
2)自定义断言,XXXRoutePredicateFactory规则

自定义模版:

  • 继承AbstractRoutePredicateFactory抽象类
  • 实现RoutePredicateFactory接口
  • 开头任意取名,但是必须以RoutePredicateFactory后缀结尾

编写步骤

1:新建MyRoutePredicateFactory类并继承AbstractRoutePredicateFactory类
package com.atguigu.cloud.config;

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.function.Predicate;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {



}
2:重写apply方法
package com.atguigu.cloud.config;

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.function.Predicate;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
        return null;
    }

}
3:新建静态内部类Config方法
package com.atguigu.cloud.config;

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.function.Predicate;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
        return null;
    }
    @Validated
    public static class Config {
        @Getter
        @Setter
        @NotEmpty
        private String userType;
    }
}
4:空参构造方法,内部调用super
package com.atguigu.cloud.config;

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.function.Predicate;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    public MyRoutePredicateFactory() {
        super(Config.class);
    }
    
    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
        return null;
    }
    @Validated
    public static class Config {
        @Getter
        @Setter
        @NotEmpty
        private String userType;
    }
}
5:重写apply方法第二版
package com.atguigu.cloud.config;

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.function.Predicate;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

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

    @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;
                }
                //如果参数存在则和config比较
                if(userType.equals(config.getUserType())){
                    return true;
                }

                return false;
            }
        };
    }
    @Validated
    public static class Config {
        @Getter
        @Setter
        @NotEmpty
        private String userType;
    }
}
6:实现shortcutFieldOrder方法,使其支持短格式
package com.atguigu.cloud.config;

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;

/**
 * @ClassName MyRoutePredicateFactory
 * @Author link
 * @Date: 2024/11/7 上午10:10
 * @Version v1.0
 * @Description:
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {


    //实现shortcutFieldOrder使其支持短格式写法
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }



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

    @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;
                }
                //如果参数存在则和config比较
                if(userType.equals(config.getUserType())){
                    return true;
                }

                return false;
            }
        };
    }
    @Validated
    public static class Config {
        @Getter
        @Setter
        @NotEmpty
        private String userType;
    }
}

7:配置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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
8:测试

在这里插入图片描述

在这里插入图片描述

3、Filter(过滤)

1)概述

过滤器分别会在请求被执行前调用或被执行后调用,用来修改请求和响应信息;

作用:

可以做请求鉴权,异常处理等;

类型:

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

单一内置过滤器GatewayFilter

1:请求头(RequestHeader)相关组

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

新增8001模块PayGateWayController方法

package com.atguigu.cloud.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.service.PayService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Enumeration;

/**
 * @ClassName PayGateWayController
 * @Author link
 * @Date: 2024/11/6 下午3:56
 * @Version v1.0
 * @Description:
 */
@RestController
public class PayGateWayController {
    @Resource
    PayService payService;

    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData<Pay> getById(@PathVariable("id") Integer id)
    {
        Pay pay = payService.getById(id);
        return ResultData.success(pay);
    }

    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
    }

    @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-atguigu1")
                    || headName.equalsIgnoreCase("X-Request-atguigu2")) {
                result = result+headName + "\t " + headValue +" ";
            }
        }
        return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
    }
}

修改9527yml文件

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - 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,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2

测试:

在这里插入图片描述

The RemoveRequestHeader GatewayFilter Factory (删除请求头Byname)

以删除sec-fetch-site为例

在这里插入图片描述

修改9527yml文件

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - 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,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site

测试:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The SetRequestHeader GatewayFilter Factory (修改请求头Byname)

以sec-fetch-mode为例:
在这里插入图片描述

修改9527yml文件

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - 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,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink

测试:

在这里插入图片描述

2:请求参数(RequestParameter)相关组

The AddRequestParameter GatewayFilter Factory(添加请求参数) 和 The RemoveRequestParameter GatewayFilter Factory(拦截请求参数)

修改9527yml文件

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - 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,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null

修改PayGateWayController方法

package com.atguigu.cloud.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.service.PayService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Enumeration;

/**
 * @ClassName PayGateWayController
 * @Author link
 * @Date: 2024/11/6 下午3:56
 * @Version v1.0
 * @Description:
 */
@RestController
public class PayGateWayController {
    @Resource
    PayService payService;

    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData<Pay> getById(@PathVariable("id") Integer id)
    {
        Pay pay = payService.getById(id);
        return ResultData.success(pay);
    }

    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
    }

    @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-atguigu1")
                    || headName.equalsIgnoreCase("X-Request-atguigu2")) {
                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());
    }
}

测试:

1、访问http://localhost:9527/pay/gateway/filter 测试添加请求参数

在这里插入图片描述

2、访问http://localhost:9527/pay/gateway/filter?customerId=99999&customerName=link

可以发现customerId的值会发生变化,customerName还是null,说明被拦截

在这里插入图片描述

3:回应头(ResponseHeader)相关组

The AddResponseHeader GatewayFilter Factory (增加响应头参数)、The SetResponseHeader GatewayFilter Factory(修改响应头参数)和The RemoveResponseHeader GatewayFilter Factory(删除响应头参数)

设置前浏览器响应头:

在这里插入图片描述

修改9527yml文件

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            #- Weight=group1, 8
            - 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,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除

测试:

在这里插入图片描述

4:前缀和路径相关组

The PrefixPath GatewayFilter Factory (自动添加路径前缀)

之前正确访问地址:http://localhost:9527/pay/gateway/filter

修改之后访问地址:http://localhost:9527/gateway/filter

/pay前缀由过滤器统一管理

修改9527yml

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


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

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
           # - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
            - Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
          filters:
            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter 隐藏的前缀

测试:

在这里插入图片描述

The SetPath GatewayFilter Factory (访问路径修改)

浏览器访问地址: http://localhost:9527/XYZ/abc/filter

实际微服务地址:http://localhost:9527/pay/gateway/filter

修改9527yml

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


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

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
           # - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
           # - Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
            - Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
          filters:
#            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置
#            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
#            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
#            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
#            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
#            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
#            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter 隐藏的前缀
            - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致

测试:

在这里插入图片描述

The RedirectTo GatewayFilter Factory (重定向到某个页面)

修改9527yml

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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


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

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
           # - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
           # - Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
            #- Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
            - Path=/pay/gateway/filter/** # 真实地址
          filters:
#            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置
#            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
#            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
#            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
#            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
#            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
#            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter 隐藏的前缀
#            - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致
             - RedirectTo=302, http://www.baidu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.baidu.com/
5:其他

Default Filters

配置在此处相当于全局通用,自定义秒变Global

spring:
   cloud:
      gateway:
         default-filters:
         -AddResponseHeader-X-Response-Default-Red,Default-Blue
         -PrefixPath=/httpbin
3)Gateway自定义过滤器
1:自定义全局Filter

案例:统计接口调用耗时情况

自定义接口调用耗时统计全局过滤器

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

package com.atguigu.cloud.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @ClassName MyGlobalFilter
 * @Author link
 * @Date: 2024/11/7 下午3:15
 * @Version v1.0
 * @Description:
 */
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

(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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
#            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


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

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
           # - Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
            #- Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
#            - Path=/pay/gateway/filter/** # 真实地址
          filters:
#            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置
#            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
#            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
#            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
#            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
#            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
#            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter 隐藏的前缀
#            - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致
#             - RedirectTo=302, http://www.baidu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.baidu.com/

(3)MyGlobalFilter 实现

package com.atguigu.cloud.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @ClassName MyGlobalFilter
 * @Author link
 * @Date: 2024/11/7 下午3:15
 * @Version v1.0
 * @Description:
 */
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {

    private static final String BEGIN_VISIT_TIME = "beginVisitTime";


    @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();
            }
        }));
    }

    /***
     * 数字越小优先级越高
     **/
    @Override
    public int getOrder() {
        return 0;
    }
}

测试:

分别访问:http://localhost:9527/pay/gateway/get/1

http://localhost:9527/pay/gateway/info

http://localhost:9527/pay/gateway/filter

在这里插入图片描述

2:自定义条件Filter

(1)新建类名MyGatewayFilterFactory需要以GatewayFilterFactory结尾并继承AbstractGatewayFilterFactory类

package com.atguigu.cloud.config;

import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

/**
 * @ClassName MyGatewayFilterFactory
 * @Author link
 * @Date: 2024/11/7 下午3:31
 * @Version v1.0
 * @Description:
 */
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
}

(2)新建MyGatewayFilterFactory.Config类

package com.atguigu.cloud.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

/**
 * @ClassName MyGatewayFilterFactory
 * @Author link
 * @Date: 2024/11/7 下午3:31
 * @Version v1.0
 * @Description:
 */
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
    
    public static class Config{
        @Setter
        @Getter
        private String status;
    }
}

(3)重写apply方法

package com.atguigu.cloud.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @ClassName MyGatewayFilterFactory
 * @Author link
 * @Date: 2024/11/7 下午3:31
 * @Version v1.0
 * @Description:
 */
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {

    @Override
    public GatewayFilter apply(Config config) {

        return new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                System.out.println("进入自定义网关过滤器MyGatewayFilterFactory,status===="+config.getStatus());
                if (request.getQueryParams().containsKey("link")){
                    return chain.filter(exchange);
                }else {
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                }
                
            }
        };
    }

    public static class Config{
        @Setter
        @Getter
        private String status;
    }
}

(4)重写shortcutFieldOrder

package com.atguigu.cloud.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName MyGatewayFilterFactory
 * @Author link
 * @Date: 2024/11/7 下午3:31
 * @Version v1.0
 * @Description:
 */
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {

    @Override
    public List<String> shortcutFieldOrder() {
        List<String> list = new ArrayList<String>();
        list.add("status");
        return list;
    }


    @Override
    public GatewayFilter apply(Config config) {

        return new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                System.out.println("进入自定义网关过滤器MyGatewayFilterFactory,status===="+config.getStatus());
                if (request.getQueryParams().containsKey("link")){
                    return chain.filter(exchange);
                }else {
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                }

            }
        };
    }

    public static class Config{
        @Setter
        @Getter
        private String status;
    }
}

(5)空参构造方法,内部调用super

package com.atguigu.cloud.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName MyGatewayFilterFactory
 * @Author link
 * @Date: 2024/11/7 下午3:31
 * @Version v1.0
 * @Description:
 */
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
    
    
    public MyGatewayFilterFactory() {
        super(MyGatewayFilterFactory.Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        List<String> list = new ArrayList<String>();
        list.add("status");
        return list;
    }


    @Override
    public GatewayFilter apply(Config config) {

        return new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                System.out.println("进入自定义网关过滤器MyGatewayFilterFactory,status===="+config.getStatus());
                if (request.getQueryParams().containsKey("link")){
                    return chain.filter(exchange);
                }else {
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                }

            }
        };
    }

    public static class Config{
        @Setter
        @Getter
        private String status;
    }
}

(6)配置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: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service            #匹配后提供服务名称
          predicates:
#            - My=test
            #- Weight=group1, 2
            #- Query=username, \d+
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
            #- Method=GET,POST
            #- Host=**.atguigu.com
            #- Header=X-Request-Id, \d+
            # - Cookie=username,link
           # - Between=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai], 2024-11-07T09:08:00.797682100+08:00[America/Denver]
            #- Before=2024-11-07T09:05:00.797682100+08:00[America/Denver]
             #- After=2024-11-07T08:58:38.797682100+08:00[Asia/Shanghai]


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

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
           # - Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
            #- Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
#            - Path=/pay/gateway/filter/** # 真实地址
          filters:
            - My=link
#            - AddRequestHeader=X-Request-atguigu1,atguiguValue1  # 请求头kv,若一头含有多参则重写一行设置
#            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
#            - RemoveRequestHeader=sec-fetch-site      # 删除请求头sec-fetch-site
#            - SetRequestHeader=sec-fetch-mode, Blue-updatebylink # 将请求头sec-fetch-mode对应的值修改为Blue-updatebylink
#            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
#            - AddResponseHeader=X-Response-link, testResponse # 新增请求参数X-Response-link并设值为testResponse
#            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter 隐藏的前缀
#            - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致
#             - RedirectTo=302, http://www.baidu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.baidu.com/

(7)测试

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

美创科技入选2024数字政府解决方案提供商TOP100!

11月19日&#xff0c;国内专业咨询机构DBC德本咨询发布“2024数字政府解决方案提供商TOP100”榜单。美创科技凭借在政府数据安全领域多年的项目经验、技术优势与创新能力&#xff0c;入选收录。 作为专业数据安全产品与服务提供商&#xff0c;美创科技一直致力于为政府、金融、…

Java编程,配置mongoUri连接mongodb时,需对特殊字符进行转义

一、背景 java程序连接mongo有两种方式&#xff1a; 用户名和密码方式uri方式 1、用户名和密码 以用户数据库为例&#xff0c;注意看它的密码 spring:data:mongodb:host: 192.168.10.17database: db_user_serviceport: 3717username: user_servicepassword: user_service3…

MySQL底层概述—1.InnoDB内存结构

大纲 1.InnoDB引擎架构 2.Buffer Pool 3.Page管理机制之Page页分类 4.Page管理机制之Page页管理 5.Change Buffer 6.Log Buffer 1.InnoDB引擎架构 (1)InnoDB引擎架构图 (2)InnoDB内存结构 (1)InnoDB引擎架构图 下面是InnoDB引擎架构图&#xff0c;主要分为内存结构和磁…

【Github】如何使用Git将本地项目上传到Github

【Github】如何使用Git将本地项目上传到Github 写在最前面1. 注册Github账号2. 安装Git工具配置用户名和邮箱仅为当前项目配置&#xff08;可选&#xff09; 3. 创建Github仓库4. 获取仓库地址5. 本地操作&#xff08;1&#xff09;进入项目文件夹&#xff08;2&#xff09;克隆…

大事件管理系统项目总结(上)

文章目录 大事件管理系统项目总结&#xff08;上&#xff09;Pinia - 配置仓库统一管理Vue3路由配置Vue3导航拦截 大事件管理系统项目总结&#xff08;上&#xff09; Pinia - 配置仓库统一管理 使用pinia多层文件夹嵌套时&#xff0c;导入某个文件的路径会很长&#xff0c;容…

鸿蒙征文|鸿蒙心路旅程:始于杭研所集训营,升华于横店

始于杭研所 在2024年7月&#xff0c;我踏上了一段全新的旅程&#xff0c;前往风景如画的杭州&#xff0c;参加华为杭研所举办的鲲鹏&昇腾集训营。这是一个专门为开发者设计的培训项目&#xff0c;中途深入学习HarmonyOS相关技术。对于我这样一个对技术充满热情的学生来说&…

flowable流程图详细绘制教程

文章目录 前言一、flowable是什么&#xff1f;回答下之前的问题 二、flowable-modeler使用1. 使用步骤2.开始绘制弄一个请假的流程 三 加载该流程总结 前言 flowable有些晦涩难懂的东西&#xff1a; 我最开始接触的时候,还是用的activity,当时觉得好复杂,那么这次经过我自己在…

【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行

文章目录&#xff1a; 【Linux 篇】Docker 的容器之海与镜像之岛&#xff1a;于 Linux 系统内探索容器化的奇妙航行前言安装docker-centos7 【Linux 篇】Docker 的容器之海与镜像之岛&#xff1a;于 Linux 系统内探索容器化的奇妙航行 &#x1f4ac;欢迎交流&#xff1a;在学习…

linux从0到1——shell编程9

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

go项目中比较好的实践方案

工作两年来&#xff0c;我并未遇到太大的挑战&#xff0c;也没有特别值得夸耀的项目。尽管如此&#xff0c;在日常的杂项工作中&#xff0c;我积累了不少心得&#xff0c;许多实践方法也在思考中逐渐得到优化。因此&#xff0c;我在这里记录下这些心得。 转发与封装 这个需求…

Maven的安装——给Idea配置Maven

一、什么是Maven? Maven是一个开源的项目管理工具&#xff0c;它主要用于Java项目的构建、依赖管理和项目生命周期管理。 二、准备环境 maven安装之前&#xff0c;我们要先安装jdk&#xff0c;确保你已经安装了jdk环境。可以通过【win】【r】打开任务管理器&#xff0c;输入…

vscode 远程连接ssh 密钥方式

目录 1. powershell 生成key&#xff1a; 2. 在服务器上安装公钥 linux测试成功&#xff1a; 3).为了确保连接成功&#xff0c;输入如下指令以保证以下文件权限正确&#xff1a; 3 开启 ssh 密钥登录 vscode 远程连接配置 python连接测试ok 查看日志&#xff1a; 命令…

Charles抓包工具-笔记

摘要 概念&#xff1a; Charles是一款基于 HTTP 协议的代理服务器&#xff0c;通过成为电脑或者浏览器的代理&#xff0c;然后截取请求和请求结果来达到分析抓包的目的。 功能&#xff1a; Charles 是一个功能全面的抓包工具&#xff0c;适用于各种网络调试和优化场景。 它…

Echarts+VUE饼图的使用(基础使用、多个饼图功能、单组饼图对应颜色使用)

安装&#xff1a;npm install echarts --save 配置:main.js // 引入echarts import * as echarts from echarts Vue.prototype.$echarts echarts一、基础饼图&#xff08;直接拷贝就能出效果&#xff09; <div class"big-box" ref"demoEhart"><…

神经网络(系统性学习三):多层感知机(MLP)

相关文章&#xff1a; 神经网络中常用的激活函数 神经网络&#xff08;系统性学习一&#xff09;&#xff1a;入门篇 神经网络&#xff08;系统性学习二&#xff09;&#xff1a;单层神经网络&#xff08;感知机&#xff09; 多层感知机&#xff08;MLP&#xff09; 多层感…

C语言练习.if.else语句.strstr

今天在做题之前&#xff0c;先介绍一下&#xff0c;新学到的库函数strstr 想要使用它&#xff0c;要先给它一个头文件<string.h> char *strstr(const char*str1,const char*str2); 首先&#xff1a;1.strstr的返回值是char&#xff0c;字符类型的。 2.两个实参&#xff…

golang实现TCP服务器与客户端的断线自动重连功能

1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功

c语言数据结构与算法--简单实现线性表(顺序表+链表)的插入与删除

老规矩&#xff0c;点赞评论收藏关注&#xff01;&#xff01;&#xff01; 目录 线性表 其特点是&#xff1a; 算法实现&#xff1a; 运行结果展示 链表 插入元素&#xff1a; 删除元素&#xff1a; 算法实现 运行结果 线性表是由n个数据元素组成的有限序列&#xff…

textureLod lod的确定

1. 自动计算导数方法 float calculateLOD(sampler2D tex, vec2 uv) { // 计算纹理坐标的导数 vec2 dUVdx dFdx(uv); vec2 dUVdy dFdy(uv); // 计算纹理大小 vec2 textureSize textureSize(tex, 0); // 0表示基础mipmap级别 // 计算LOD float maxDeriv max(length(…

C++数据结构与算法

C数据结构与算法 1.顺序表代码模版 C顺序表模版 #include <iostream> using namespace std; // 可以根据需要灵活变更类型 #define EleType intstruct SeqList {EleType* elements;int size;int capacity; };// Init a SeqList void InitList(SeqList* list, int capa…