当前位置: 首页 > article >正文

07-SpringCloud-Gateway新一代网关

一、概述

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.kler.cn/a/409224.html

相关文章:

  • 【隐私计算大模型】联邦深度学习之拆分学习Split learning原理及安全风险、应对措施以及在大模型联合训练中的应用案例
  • 小U的奖学金申请问题
  • 七天掌握SQL--->第五天:数据库安全与权限管理
  • AIGC学习笔记(6)——AI大模型开发工程师
  • 数据指标与标签在数据分析中的关系与应用
  • 社交电商专业赋能高校教育与产业协同发展:定制开发AI智能名片及2+1链动商城小程序的创新驱动
  • Cross-Site Scripting(XSS)攻击
  • MassTransit中文文档
  • MATLAB神经网络(五)——R-CNN视觉检测
  • 什麼是ISP提供的公共IP地址?
  • 低成本TYPE-C转DP线
  • 企业OA系统:Spring Boot技术实现与管理
  • 对传统加密算法降维打击?!——量子计算
  • springMVC重点知识
  • Centos-stream 9,10 add repo
  • 对元素为 pair 的数组的各元素进行排序的方法
  • 基于之前的秒杀功能的优化(包括Sentinel在SpringBoot中的简单应用)
  • 学习记录:js算法(一百零二):使用最小花费爬楼梯
  • 9.10Ubuntu网络编程环境配置,已解决
  • 力扣 41. 缺失的第一个正数
  • 【tomcat】tomcat的默认配置
  • 【Linux】详解shell代码实现(上)
  • postman 调用 下载接口(download)使用默认名称(response.txt 或随机名称)
  • A045-基于spring boot的个人博客系统的设计与实现
  • 数据结构 ——— 希尔排序算法的实现
  • 鸿蒙NEXT开发案例:二维码的生成与识别