Gateway新一代网关,Gateway新一代智能网关

马肤

温馨提示:这篇文章已超过479天没有更新,请注意相关的内容是否还可用!

Gateway新一代网关摘要:,,Gateway推出新一代网关,具备高性能、高可靠性和安全性等特点。该网关采用最新的技术和设计理念,旨在满足不断增长的网络需求。新一代网关具备更高的数据处理能力,能够支持更多的设备和应用程序,同时提供更快的传输速度和更低的延迟。它还具备强大的安全保护功能,保护网络免受攻击和威胁。Gateway新一代网关将为用户带来更高效、更智能的网络体验。

Gateway新一代网关

1、概述

​ Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;

​ 但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关SpringCloud Gateway替代Zuul。

​ 官网:Spring Cloud Gateway 中文文档 (springdoc.cn)

Gateway新一代网关,Gateway新一代智能网关 第1张

​ 微服务架构中网关在哪里?

Gateway新一代网关,Gateway新一代智能网关 第2张

Spring Cloud Gateway能干什么?

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

    总结:

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

    Gateway新一代网关,Gateway新一代智能网关 第3张

    2、Gateway三大核心

    • Route(路由): 网关的基本构件。它由一个ID、一个目的地URI、一个谓词(Predicate)集合和一个过滤器(Filter)集合定义。如果集合谓词为真,则路由被匹配。
    • Predicate(谓词): 这是一个 Java 8 Function Predicate。输入类型是 Spring Framework ServerWebExchange。这让你可以在HTTP请求中的任何内容上进行匹配,比如header或查询参数。
    • Filter(过滤器): 这些是 GatewayFilter 的实例,已经用特定工厂构建。在这里,你可以在发送下游请求之前或之后修改请求和响应。
      1. web前端请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
      2. predicate就是我们的匹配条件;
      3. filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

      Gateway新一代网关,Gateway新一代智能网关 第4张

      3、Spring Cloud Gateway 工作流程

      Gateway新一代网关,Gateway新一代智能网关 第5张

      ​ 客户端向 Spring Cloud Gateway 发出请求。如果Gateway处理程序映射确定一个请求与路由相匹配,它将被发送到Gateway Web处理程序。这个处理程序通过一个特定于该请求的过滤器链来运行该请求。过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和之后运行逻辑。

      ​ 所有的 "pre" (前)过滤器逻辑都被执行。然后发出代理请求。在代理请求发出后,"post" (后)过滤器逻辑被运行。

      注意:在路由中定义的没有端口的URI,其HTTP和HTTPS URI的默认端口值分别为80和443。

      总结:路由转发+断言判断+执行过滤器链

      4、入门配置

      新建module,cloud-gateway9527

      Gateway新一代网关,Gateway新一代智能网关 第6张

      添加POM,添加springcloudgateway依赖。

       
              
              
                  org.springframework.cloud
                  spring-cloud-starter-gateway
              
              
              
                  org.springframework.cloud
                  spring-cloud-starter-consul-discovery
              
              
              
                  org.springframework.boot
                  spring-boot-starter-actuator
              
          
          
              
                  
                      org.springframework.boot
                      spring-boot-maven-plugin
                  
              
          
      

      ​ 写配置文件application.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}
      

      ​ 主启动类:

      @SpringBootApplication
      @EnableDiscoveryClient
      public class GateWay9527 {
          public static void main(String[] args) {
              SpringApplication.run(GateWay9527.class,args);
          }
      }
      

      ​ 业务类是不需要写的,网关与业务无关。

      ​ 先启动Consul,然后启动网关入住进服务注册中心。

      Gateway新一代网关,Gateway新一代智能网关 第7张

      5、9527网关如何做路由映射

      ​ 我们目前不希望暴露8001端口,希望在8001这个真正的支付微服务外面再套一个9527网关。

      8001新建GateWayController

      @RestController
      public class GateWayController {
          @Resource
          PayService payService;
          @GetMapping(value = "/pay/gateway/get/{id}")
          public ResultData getById(@PathVariable("id") Integer id)
          {
              Pay pay = payService.getById(id);
              return ResultData.success(pay);
          }
          @GetMapping(value = "/pay/gateway/info")
          public ResultData getGatewayInfo()
          {
              return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
          }
      }
      

      ​ 测试一下:

      Gateway新一代网关,Gateway新一代智能网关 第8张

      ​ 没有问题,下面在网关的配置文件中新增配置,新增路由和断言配置。

      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/**              # 断言,路径相匹配的进行路由
      

      ​ 添加网关之后的访问就不是8001了,应该是localhost:9527/pay/gateway/get/1

      Gateway新一代网关,Gateway新一代智能网关 第9张

      ​ 目前通过网关访问是成功的,如果通过80访问网关然后再访问8001呢?

      ​ 我们启动80订单微服务,它从Consul注册中心通过微服务名称找到8001支付微服务进行调用,

      ​ 80 → 9527 → 8001

      ​ 要求访问9527网关后才能访问8001,如果我们此时启动80订单,可以做到吗?

      ​ 修改cloud-api-commons的api接口添加网关测试方法

      //网关测试
      @GetMapping(value = "/pay/gateway/get/{id}")
      public ResultData getById(@PathVariable("id") Integer id);
      @GetMapping(value = "/pay/gateway/info")
      public ResultData getGatewayInfo();
      

      ​ cloud-consumer-feign-order80添加网关测试的controller

      @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 getGatewayInfo()
          {
              return payFeignApi.getGatewayInfo();
          }
      }
      

      Gateway新一代网关,Gateway新一代智能网关 第10张

      ​ 我们发现是可以访问的,真的走网关了吗?我们的API接口上@FeignClient(value = "cloud-payment-service")打的可是cloud-payment-service微服务,根本没有网关的事呀,所以,这个时候的网关压根就没有使用,我们把网关的微服务关掉再用80访问一定是可以访问的。

      Gateway新一代网关,Gateway新一代智能网关 第11张

      ​ 网关的9527关掉了,现在访问

      Gateway新一代网关,Gateway新一代智能网关 第12张

      ​ 依旧正常访问。我们想一下,API上@FeignClient注解上原来就是cloud-payment-service,我们换成网关的服务名称cloud-gateway不就成了。

      //@FeignClient(value = "cloud-payment-service")
      @FeignClient(value = "cloud-gateway")  //换成网关微服务
      public interface PayFeignApi {
          /**
           * 新增一条支付相关流水记录
           * @param payDTO
           * @return
           */
          @PostMapping("/pay/add")
          public ResultData addPay(@RequestBody PayDTO payDTO);
          //通过id查询
          @GetMapping(value = "/pay/get/{id}")
          public ResultData getPayById(@PathVariable("id") Integer id);
          //删除
          @DeleteMapping("/pay/del/{id}")
          public ResultData delById(@PathVariable("id") Integer integer);
          //修改
          @PutMapping("/pay/update")
          public ResultData update(@RequestBody PayDTO payDTO);
          //查全部
          @GetMapping("/pay/getall")
          public ResultData getAll();
          //openfeign天然支持负载均衡演示
          @GetMapping("/pay/getInfo")
          public String myLB();
          //=========Resilience4j CircuitBreaker 的例子
          @GetMapping("/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);
          @GetMapping(value = "/pay/micrometer/{id}")
          public String myMicrometer(@PathVariable("id") Integer id);
          //网关测试
          @GetMapping(value = "/pay/gateway/get/{id}")
          public ResultData getById(@PathVariable("id") Integer id);
          @GetMapping(value = "/pay/gateway/info")
          public ResultData getGatewayInfo();
      }
      

      ​ 重启80微服务,再次测试

      ​ 无网关的直接500了

      Gateway新一代网关,Gateway新一代智能网关 第13张

      Gateway新一代网关,Gateway新一代智能网关 第14张

      ​ 再把网关打开就成功访问了

      Gateway新一代网关,Gateway新一代智能网关 第15张

      目前我们的配置还是有问题的,比如我们网关中的uri地址,本地加端口号写的死死的,一改就无了…

      Gateway新一代网关,Gateway新一代智能网关 第16张

      6、GateWay高级特性

      6.1、Route以微服务名动态获取服务URI

      Gateway新一代网关,Gateway新一代智能网关 第17张

      ​ 我们之前给URI写死了,现在可以修改成它的微服务名称,这样就可以动态的从服务注册中心拿到具体的地址加端口,即使端口更改了也没有问题。URL中添加一个lb代表SpringCloud的负载均衡ReactorLoadBalancer。

      ​ 将9527的配置文件再来修改一下

      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/**              # 断言,路径相匹配的进行路由
      

      ​ 修改以后可以重启一下网关测试。

      Gateway新一代网关,Gateway新一代智能网关 第18张

      ​ 测试没有问题,我们把8001的端口给改成8003再测试一下。

      Gateway新一代网关,Gateway新一代智能网关 第19张

      Gateway新一代网关,Gateway新一代智能网关 第20张

      ​ 依然可用。

      6.2、Predicate断言(谓词)

      ​ Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping 基础设施的一部分。Spring Cloud Gateway包括许多内置的路由谓词工厂。所有这些谓词都与HTTP请求的不同属性相匹配。你可以用逻辑 and 语句组合多个路由谓词工厂。

      ​ 我们可以查看9527后台输出的默认路由谓词是和官网的那12个默认路由谓词一一对应着的

      Gateway新一代网关,Gateway新一代智能网关 第21张

      ​ 两种配置方式

      • Shortcut Configuration,快捷方式配置由过滤器名称(filter name),后面跟一个等号 (=),然后是用逗号 (,) 分隔的参数值。

        Gateway新一代网关,Gateway新一代智能网关 第22张

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

        Gateway新一代网关,Gateway新一代智能网关 第23张

        常用的默认路由谓词解释

        1. After 路由谓词工厂需要一个参数,即一个日期时间(这是一个java ZonedDateTime),这个谓词匹配发生在指定日期时间之后的请求。

          那么这个日期怎么获得?

          写一个普通的java类来获得。

          public class ZonedDateTimeDemo
          {
              public static void main(String[] args)
              {
                  System.out.println(ZonedDateTime.now());
              }
          }
          

          获得时间格式:2024-03-17T20:25:30.218129200+08:00[Asia/Shanghai]

          开始配置

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  - After=2024-03-17T20:30:30.218129200+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/**              # 断言,路径相匹配的进行路由
          

          Gateway新一代网关,Gateway新一代智能网关 第24张

          在我设置的8:30:30之前是不能访问的,8点半之后就可以访问了。

        2. Before 路由谓词工厂只需要一个参数,即 datetime,这个谓词匹配发生在指定日期时间datetime之前的请求。

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  - After=2024-03-17T20:30:30.218129200+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/**              # 断言,路径相匹配的进行路由
                  - Before=2024-03-17T20:39:00.218129200+08:00[Asia/Shanghai] 
          

          Gateway新一代网关,Gateway新一代智能网关 第25张

          可以看到8.38还能正常访问的39就不能了。

        3. Between 路由谓词工厂需要两个参数,datetime1 和 datetime2,它们是java ZonedDateTime 对象。这个谓词匹配发生在 datetime1 之后和 datetime2 之前也就是这个时间段的请求。

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  - Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+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/**              # 断言,路径相匹配的进行路由
                  - Before=2024-03-17T20:39:00.218129200+08:00[Asia/Shanghai]
          

          Gateway新一代网关,Gateway新一代智能网关 第26张

          可以看到,这个只能在9点到9点零1才能访问到。

        4. Cookie 路由谓词工厂接受两个参数,即 cookie name 和一个 regexp(这是一个Java正则表达式)。这个谓词匹配具有给定名称且其值符合正则表达式的cookie。

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  - Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+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/**              # 断言,路径相匹配的进行路由
                  - Cookie=username, zm
          

          只有加了cookie才能访问,而且键值(kv)要匹配

          有三种可以带cookie访问的方法

          • 方法1,使用原生命令,cmd打开运行框

            不带cookie的不能访问

            Gateway新一代网关,Gateway新一代智能网关 第27张

            带了cookie可以访问

            Gateway新一代网关,Gateway新一代智能网关 第28张

          • 方法2,使用postman测试工具测试

            不带cookie的不能访问

            Gateway新一代网关,Gateway新一代智能网关 第29张

            带了cookie可以访问

            Gateway新一代网关,Gateway新一代智能网关 第30张

          • 方法3,使用浏览器控制台实现

            不带cookie或者故意填错误的不能访问

            Gateway新一代网关,Gateway新一代智能网关 第31张

            带了正确的cookie可以访问

            Gateway新一代网关,Gateway新一代智能网关 第32张

          • Header 路由谓词工厂需要两个参数,header 和一个 regexp(这是一个Java正则表达式)。这个谓词与具有给定名称且其值与正则表达式相匹配的 header 匹配。

            gateway:
              routes:
                - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                  #uri: http://localhost:8001                #匹配后提供服务的路由地址
                  uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                  predicates:
                    - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                    #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                    - Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                 # uri: http://localhost:8001                #匹配后提供服务的路由地址
                  uri: lb://cloud-payment-service
                  predicates:
                    - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
                    - Cookie=username, zm
            

            测试方法1,使用原生命令

            不是正整数

            Gateway新一代网关,Gateway新一代智能网关 第33张

            是正整数

            Gateway新一代网关,Gateway新一代智能网关 第34张

            测试方法2,使用postman测试

            不是正整数

            Gateway新一代网关,Gateway新一代智能网关 第35张

            是正整数

            Gateway新一代网关,Gateway新一代智能网关 第36张

          • Host 路由谓语工厂接受一个参数:一个主机(Host)名称的 patterns 列表。该pattern是Ant风格的模式,以 . 为分隔符。这个谓词匹配符合该pattern的Host header。

            gateway:
              routes:
                - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                  #uri: http://localhost:8001                #匹配后提供服务的路由地址
                  uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                  predicates:
                    - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                    #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                    - Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                 # uri: http://localhost:8001                #匹配后提供服务的路由地址
                  uri: lb://cloud-payment-service
                  predicates:
                    - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
                    #- Cookie=username, zm
                    - Host=**.zmblog.com,**.zm.cn  #请求host的header值带zmblog.com或zm.cn的可以匹配
            

            使用原命令测试

            正确符合规则的可以访问

            Gateway新一代网关,Gateway新一代智能网关 第37张

            不符合规则的拒绝访问

            Gateway新一代网关,Gateway新一代智能网关 第38张

            使用postman测试

            正常匹配规则的

            Gateway新一代网关,Gateway新一代智能网关 第39张

        ​ 不符合规则的

        Gateway新一代网关,Gateway新一代智能网关 第40张

        7.Path 路由谓词工厂需要两个参数:一个Spring PathMatcher patterns 的list和一个可选的flag matchTrailingSlash(默认为 true)。我们最开始用的就是这个,就不再看了。

        8.Query 路由谓词工厂需要两个参数:一个必需的 param 和一个可选的 regexp(这是一个Java正则表达式)。

        gateway:
          routes:
            - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
              #uri: http://localhost:8001                #匹配后提供服务的路由地址
              uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
              predicates:
                - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                #- Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                - Query=username,\d+  #要有参数名称为username并且值还要是整数才能路由
            - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
             # uri: http://localhost:8001                #匹配后提供服务的路由地址
              uri: lb://cloud-payment-service
              predicates:
                - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
                #- Cookie=username, zm
                - Host=**.zmblog.com,**.zm.cn  #请求host的header值带zmblog.com或zm.cn的可以匹配
        

        ​ 测试:

        ​ 按照规则访问

        Gateway新一代网关,Gateway新一代智能网关 第41张

        ​ 不按规则不能访问

        Gateway新一代网关,Gateway新一代智能网关 第42张

        9.RemoteAddr 路由谓词工厂接受一个 sources 集合(最小长度为1),它是CIDR注解(IPv4或IPv6)字符串,如 192.168.0.1/16(其中 192.168.0.1 是一个IP地址,16 是一个子网掩码)。

        gateway:
          routes:
            - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
              #uri: http://localhost:8001                #匹配后提供服务的路由地址
              uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
              predicates:
                - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                #- Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                #- Query=username,\d+  #要有参数名称为username并且值还要是整数才能路由
                - RemoteAddr=10.2.142.1/24  # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
            - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
             # uri: http://localhost:8001                #匹配后提供服务的路由地址
              uri: lb://cloud-payment-service
              predicates:
                - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
                #- Cookie=username, zm
                - Host=**.zmblog.com,**.zm.cn  #请求host的header值带zmblog.com或zm.cn的可以匹配
        

        ​ 测试,重启服务按照原来的localhost地址访问一下不能访问。

        Gateway新一代网关,Gateway新一代智能网关 第43张

        ​ 换成我们本地的IP就可以了

        Gateway新一代网关,Gateway新一代智能网关 第44张

        10.Method 路由谓词工厂接受一个 methods 参数,它是一个或多个参数:要匹配的HTTP方法。

        ​ 我们可以限制只能使用GET或者POST方法才能访问。

        - Method=GET,POST   #只能是get或post请求方法
        

        Gateway新一代网关,Gateway新一代智能网关 第45张

        6.3、自定义断言XXXRoutePredicateFactory规则

        ​ 原有的默认的路由断言规则不够用,我们就自定义一个。

        ​ 查看AfterRoutePredicateFactory它就是继承了AbstractRoutePredicateFactory

        public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory
        

        ​ 然后再点AbstractRoutePredicateFactory里面它又实现了RoutePredicateFactory接口

        Gateway新一代网关,Gateway新一代智能网关 第46张

        ​ 所以我们要想自定义一个路由断言就需要这几点

        1. 要么继承AbstractRoutePredicateFactory抽象类;
        2. 要么实现RoutePredicateFactory接口;
        3. 开头的名字任意取,但是必须以RoutePredicateFactory为后缀结尾;
        4. 由于AbstractRoutePredicateFactory里面就实现类RoutePredicateFactory接口我们就直接继承它即可,一举两得;
        • 新建类名XXX需要以RoutePredicateFactory为后缀结尾并继承AbstractRoutePredicateFactory抽象类;

          @Component
          public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory
          
        • 重写apply方法;

          @Override
          public Predicate apply(MyRoutePredicateFactory.Config config) {
              return null;
          }
          
        • 新建apply方法所需要的静态内部类MyRoutePredicateFactory.Config,这个Config类就是我们的路由断言规则,非常重要;

          @Validated 
          public static class Config{
              @Setter@Getter@NotNull
              private String userType;  //会员类型
          }
          
        • 空参构造方法,内部调用super;

          //空参构造函数
          public MyRoutePredicateFactory() {
              super(Config.class);
          }
          
        • 重写apply方法第二版;

          @Override
          public Predicate apply(MyRoutePredicateFactory.Config config) {
              return new GatewayPredicate() {
                  @Override
                  public boolean test(ServerWebExchange serverWebExchange) {
                      String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                      if (userType == null) {
                          return false;
                      }
                      //这个config是从配置文件中拿到的如果和传来的相匹配就通过
                      if (userType.equals(config.getUserType())){
                          return true;
                      }
                      return false;
                  }
              };
          }
          
        • 完整方法

          //业务需求说明:自定义配置会员等级userType,按照钻石/黄金/青铜的等级,yml配置会员等级
          @Component
          public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {
              @Override
              public Predicate apply(MyRoutePredicateFactory.Config config) {
                  return new GatewayPredicate() {
                      @Override
                      public boolean test(ServerWebExchange serverWebExchange) {
                          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{
                  @Setter@Getter@NotNull
                  private String userType;  //会员类型
              }
              //空参构造函数
              public MyRoutePredicateFactory() {
                  super(Config.class);
              }
          }
          
        • 把自定义的断言配置到yml文件

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                  #- Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                  #- Query=username,\d+  #要有参数名称为username并且值还要是整数才能路由
                  #- RemoteAddr=10.2.142.1/24  # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
                  #- Method=GET,POST   #只能是get或post请求方法
                  - My=diamond  #自定义的断言
              - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
               # uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service
                predicates:
                  - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
                  #- Cookie=username, zm
                  - Host=**.zmblog.com,**.zm.cn  #请求host的header值带zmblog.com或zm.cn的可以匹配
          

          ​ 重启测试发现报错了

          Gateway新一代网关,Gateway新一代智能网关 第47张

          ​ 报错说没绑定快捷方式的配置

          Caused by: org.springframework.boot.context.properties.bind.validation.BindValidationException: Binding validation errors on 
          

          ​ 那我们就用完全展开的配置方式再次重写yml

          gateway:
            routes:
              - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
                #uri: http://localhost:8001                #匹配后提供服务的路由地址
                uri: lb://cloud-payment-service               #匹配后提供服务的路由地址
                predicates:
                  - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
                  #- Between=2024-03-17T21:00:00.218129200+08:00[Asia/Shanghai],2024-03-17T21:01:00.218129200+08:00[Asia/Shanghai]  #在这个时间之后才能够访问,到点放票
                  #- Header=X-Request-Id, \d+  #只有X-Request-Id属性为正整数才能访问
                  #- Query=username,\d+  #要有参数名称为username并且值还要是整数才能路由
                  #- RemoteAddr=10.2.142.1/24  # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
                  #- Method=GET,POST   #只能是get或post请求方法
                 # - My=diamond  #自定义的断言
                  - name: My
                    args:
                      userType: diamond     #使用完全展开的方式配置
          

          ​ 重启不报错,测试一下

          ​ 带正确参数的访问

          Gateway新一代网关,Gateway新一代智能网关 第48张

          ​ 不带参数或者不是配置文件中写的userType就不能访问

          Gateway新一代网关,Gateway新一代智能网关 第49张

          ​ 修改一下自定义断言MyRoutePredicateFactory,添加方法shortcutFieldOrder能使用短配置

          //实现短配置方式
          public List shortcutFieldOrder() {
              return Collections.singletonList("userType");
          }
          

          ​ 现在的完整MyRoutePredicateFactory代码

          //业务需求说明:自定义配置会员等级userType,按照钻石/黄金/青铜的等级,yml配置会员等级
          @Component
          public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {
              @Override
              public Predicate apply(MyRoutePredicateFactory.Config config) {
                  return new GatewayPredicate() {
                      @Override
                      public boolean test(ServerWebExchange serverWebExchange) {
                          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{
                  @Setter@Getter@NotNull
                  private String userType;  //会员类型
              }
              //空参构造函数
              public MyRoutePredicateFactory() {
                  super(Config.class);
              }
              //实现短配置方式
              public List shortcutFieldOrder() {
                  return Collections.singletonList("userType");
              }
          }
          

          ​ 到配置文件中使用短配置方式配置测试

                      - My=diamond  #自定义的断言
          #            - name: My
          #              args:
          #                userType: diamond     #使用完全展开的方式配置
          

          Gateway新一代网关,Gateway新一代智能网关 第50张

          6.4、Filter过滤

          6.4.1、Filter概述

          ​ 路由(Route)过滤器(Filter)允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是一个特定的路由。Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。

          ​ 中文官网:Spring Cloud Gateway 中文文档 (springdoc.cn)

          ​ 其实就相当于SpringMVC里面的拦截器interceptor,Servlet过滤器。"pre"和"post"分别会在请求被执行前调用和被执行后调用,用来修改请求和响应信息。

          能干嘛?

          • 请求鉴权;
          • 异常处理;
          • 记录接口调用时长统计(重点)

            类型

            • 全局默认过滤器Global Filters;

              gateway出厂默认已经有的,直接使用,主要作用于所有的路由,不需要在配置文件中配置,作用在所有的路由上,实现GlobalFilter接口即可。

            • 单一内置过滤器GatewayFilter;

              也可以称为网关过滤器,这种过滤器主要是作用于单一路由或者某个路由分组

            • 自定义过滤器;

              6.4.2、Gateway内置Filter

              一些常用的

              1. 请求头(RequestHeader)相关组;

                对应着官网的

                6.1.The AddRequestHeader GatewayFilter Factory

                指定请求头内容ByName

                在8001微服务的GateWayController中新增方法

                //测试The AddRequestHeader GatewayFilter Factory
                @GetMapping("/pay/gateway/filter")
                public ResultData getGatewayFilter(HttpServletRequest request){
                    String result = "";
                    Enumeration headers = request.getHeaderNames();
                    while (headers.hasMoreElements()) {
                        String headName = headers.nextElement();
                        String headerValue = request.getHeader(headName);
                        System.out.println("请求头名:"+headName+"\t\t\t"+"请求值:"+headerValue);
                        if (headName.equalsIgnoreCase("X-Request-zm1") || headName.equalsIgnoreCase("X-Request-zm2")){
                            result = result + headName + "\t" + headerValue +" ";
                        }
                    }
                    return ResultData.success("getGatewayFilter过滤器test:"+result+" \t "+ DateUtil.now());
                }
                

                9527配置文件添加过滤内容

                - id: pay_routh3
                  uri: lb://cloud-payment-service
                  predicates:
                    - Path=/pay/gateway/filter/**
                  filters:
                    - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置
                    - AddRequestHeader=X-Request-zm2,zmValue2  #请求头kv,如果一头含有多参数则重写一行设置
                

                启动9527和8001并再次调用localhost:9527/pay/gateway/filter

                Gateway新一代网关,Gateway新一代智能网关 第51张

                查看后台

                Gateway新一代网关,Gateway新一代智能网关 第52张

                6.18.The RemoveRequestHeader GatewayFilter Factory

                可以删除请求头的内容根据请求头名

                我们把名为sec-fetch-site的请求头删除掉

                - id: pay_routh3
                  uri: lb://cloud-payment-service
                  predicates:
                    - Path=/pay/gateway/filter/**
                  filters:
                    - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置指定请求头内容    
                    - AddRequestHeader=X-Request-zm2,zmValue2  #请求头kv,如果一头含有多参数则重写一行设置
                    - RemoveRequestHeader= sec-fetch-site #删除请求头sec-fetch-site
                

                重启测试

                Gateway新一代网关,Gateway新一代智能网关 第53张

                6.29.The SetRequestHeader GatewayFilter Factory

                可以修改请求头的值,那我们把请求头名为sec-fetch-mode的请求值修改成myNavigate

                - id: pay_routh3
                  uri: lb://cloud-payment-service
                  predicates:
                    - Path=/pay/gateway/filter/**
                  filters:
                    - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置指定请求头内容    
                    - AddRequestHeader=X-Request-zm2,zmValue2  #请求头kv,如果一头含有多参数则重写一行设置
                    - RemoveRequestHeader= sec-fetch-site #删除请求头sec-fetch-site
                    - SetRequestHeader=sec-fetch-mode,myNavigate  #把请求头名为sec-fetch-mode的请求值修改成myNavigate
                

                重启测试

                Gateway新一代网关,Gateway新一代智能网关 第54张

              2. 请求参数(RequestParameter)相关组;

                此组分别对应着

                6.3、The AddRequestParameter GatewayFilter Factory,在请求中添加参数

                6.19、The RemoveRequestParameter GatewayFilter Factory删除请求中的参数值

                这两个同时演示,在配置文件中配置

                filters:
                  - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置指定请求头内容    
                  - AddRequestHeader=X-Request-zm2,zmValue2  #请求头kv,如果一头含有多参数则重写一行设置
                  - RemoveRequestHeader= sec-fetch-site #删除请求头sec-fetch-site
                  - SetRequestHeader=sec-fetch-mode,myNavigate  #把请求头名为sec-fetch-mode的请求值修改成myNavigate
                  - AddRequestParameter=customerID,9527 #新增请求参数的kv
                  - RemoveRequestParameter=customerName        # 删除url请求参数customerName,你传递过来也是null
                

                修改一下GateWayController,获取请求的参数并输出。

                //测试The AddRequestHeader GatewayFilter Factory
                @GetMapping("/pay/gateway/filter")
                public ResultData getGatewayFilter(HttpServletRequest request){
                    String result = "";
                    Enumeration headers = request.getHeaderNames();
                    while (headers.hasMoreElements()) {
                        String headName = headers.nextElement();
                        String headerValue = request.getHeader(headName);
                        System.out.println("请求头名:"+headName+"\t\t\t"+"请求值:"+headerValue);
                        if (headName.equalsIgnoreCase("X-Request-zm1") || headName.equalsIgnoreCase("X-Request-zm2")){
                            result = result + headName + "\t" + headerValue +" ";
                        }
                    }
                    System.out.println("----------------------------------");
                    String customerID = request.getParameter("customerID");
                    System.out.println("参数customerID:"+customerID);
                    System.out.println("----------------------------------");
                    String customerName = request.getParameter("customerName");
                    System.out.println("参数customerName:"+customerName);
                    System.out.println("----------------------------------");
                    
                    return ResultData.success("getGatewayFilter过滤器test:"+result+" \t "+ DateUtil.now());
                }
                

                启动测试,我们先不添加参数直接发请求。

                Gateway新一代网关,Gateway新一代智能网关 第55张

                然后在请求中添加参数http://localhost:9527/pay/gateway/filter?customerID=6666&customerName=zzzmmm

                Gateway新一代网关,Gateway新一代智能网关 第56张

                原先在配置文件中写死的customerID会被你的请求覆盖掉,而参数customerName是要被移除的参数,所以你传入什么都会被移除为null

              3. 响应头(ResponseHeader)相关组;

                • 6.4.The AddResponseHeader GatewayFilter Factory添加响应头
                • 6.30.The SetResponseHeader GatewayFilter Factory修改响应头
                • 6.20.The RemoveResponseHeader GatewayFilter Factory移除响应头

                  配置文件修改,新增一个响应头X-Response-zm并设值为ZMResponse,修改响应头时间Date为2066-12-25,然后将自带的Content-Type 响应属性删除。

                  filters:
                    - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置指定请求头内容    
                    - AddRequestHeader=X-Request-zm2,zmValue2  #请求头kv,如果一头含有多参数则重写一行设置
                    - RemoveRequestHeader= sec-fetch-site #删除请求头sec-fetch-site
                    - SetRequestHeader=sec-fetch-mode,myNavigate  #把请求头名为sec-fetch-mode的请求值修改成myNavigate
                    - AddRequestParameter=customerID,9527 #新增请求参数的kv
                    - RemoveRequestParameter=customerName        # 删除url请求参数customerName,你传递过来也是null
                    - AddResponseHeader=X-Response-zm,ZMResponse #新增一个响应头X-Response-zm并设值为ZMResponse
                    - SetResponseHeader=Date,2066-12-25 #修改响应头时间Date为2066-12-25
                    - RemoveResponseHeader=Content-Type #将自带的Content-Type 响应属性删除
                  

                  重启服务查看效果

                  Gateway新一代网关,Gateway新一代智能网关 第57张

                • 前缀和路径相关组;

                  • 6.14.The PrefixPath GatewayFilter Factory自动添加路劲前缀

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

                    - id: pay_routh3
                      uri: lb://cloud-payment-service
                      predicates:
                       # - Path=/pay/gateway/filter/**
                        - Path=/gateway/filter/**    #实际上你应该在浏览器输入http://localhost:9527/gateway/filter
                      filters:
                         - PrefixPath=/pay   #和上面的Path拼在一起就是http://localhost:9527/pay/gateway/filter
                    

                    现在的访问地址就是http://localhost:9527/gateway/filte了

                    Gateway新一代网关,Gateway新一代智能网关 第58张

                    如果还访问原来的地址就是404了

                    Gateway新一代网关,Gateway新一代智能网关 第59张

                  • 6.29.The SetPath GatewayFilter Factory修改访问路劲

                    此时访问的地址就变成了localhost:9527/ZM/abcd/filter才能正确访问

                    - id: pay_routh3
                      uri: lb://cloud-payment-service
                      predicates:
                       # - Path=/pay/gateway/filter/**
                       # - Path=/gateway/filter/**    #实际上你应该在浏览器输入http://localhost:9527/gateway/filter
                         - Path=/ZM/abcd/{segment}  #修改访问路径,{segment}占位符的内容会和SetPath的{segment}保持一致
                      filters:
                         - SetPath=/pay/gateway/{segment}
                    

                    Gateway新一代网关,Gateway新一代智能网关 第60张

                    最后的那个占位符写错你就访问不了了

                    Gateway新一代网关,Gateway新一代智能网关 第61张

                    那如果把占位符的写对,前面自己改的写错呢?

                    Gateway新一代网关,Gateway新一代智能网关 第62张

                    还是不能访问的连前面都不匹配。

                  • 6.16. The RedirectTo GatewayFilter Factory重定向到某界面

                    - id: pay_routh3
                      uri: lb://cloud-payment-service
                      predicates:
                         - Path=/pay/gateway/filter/**
                       # - Path=/gateway/filter/**    #实际上你应该在浏览器输入http://localhost:9527/gateway/filter
                         #- Path=/ZM/abcd/{segment}  #修改访问路径,{segment}占位符的内容会和SetPath的{segment}保持一致
                      filters:
                         - RedirectTo=302,http://www.zmblog.vip #访问localhost:9527/pay/gateway/filter/ 直接跳转到我的个人博客上
                    

                    直接跳转过来

                    Gateway新一代网关,Gateway新一代智能网关 第63张

                  • 其它

                    6.38.Default Filters配置在此处相当于全局通用,自定义秒变Global。

                    GlobalFilter 接口的签名与 GatewayFilter 相同。这些是特殊的过滤器,有条件地应用于所有路由。

              6.4.3、Gateway自定义Filter

              自定义全局Filter

              ​ 对于我们之前说的那个面试题,解决统计接口调用耗时情况的,怎么实现,就可以使用自定义全局过滤器的方式搞定。

              官网说明:

              Gateway新一代网关,Gateway新一代智能网关 第64张

              ​ 我们参照官网的示例写出自己的全局Filter

              @Component
              @Slf4j
              public class MyGlobal implements GlobalFilter, Ordered {
                  public static final String START_TIME = "start_time";
                  @Override
                  public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                       //先记录访问接口开始的时间
                       exchange.getAttributes().put(START_TIME,System.currentTimeMillis());
                       //调用chain.filter(exchange),将请求传递给下一个过滤器或最终的目标服务。
                      //使用then方法确保在请求处理完成后执行一些操作
                      return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                          Long startTime = exchange.getAttribute(START_TIME);
                          if (startTime != 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()-startTime)+"毫秒");
                              System.out.println("----------------------分割线---------------------------");
                          }
                      }));
                  }
                  //返回的值越小优先级别越高
                  @Override
                  public int getOrder() {
                      return -1;
                  }
              }
              

              ​ 配置文件yml

                 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/**              # 断言,路径相匹配的进行路由
                      - id: pay_routh3
                        uri: lb://cloud-payment-service
                        predicates:
                           - Path=/pay/gateway/filter/**
                        filters:
                          - AddRequestHeader=X-Request-zm1,zmValue1  #请求头kv,如果一头含有多参数则重写一行设置指定请求头内容
                          - AddRequestHeader=X-Request-zm2,zmValue2  
              

              ​ 重启测试一下

              Gateway新一代网关,Gateway新一代智能网关 第65张

              自定义条件Filter

              ​ 自定义,单一内置过滤器GatawayFilter,可以先参考GateWay内置出厂默认的然后照猫画虎,具体的内容感觉还有点像前面自定义的断言。

              Gateway新一代网关,Gateway新一代智能网关 第66张

              自定义网关过滤器规则

              1. 新建类名XXX需要以GatewayFilterFactory结尾并继承AbstractGatewayFilterFactory类;

              2. 新建MyGatewayFilterFactory.Config内部类;

                public static class Config{
                    @Getter@Setter
                    private String status;//设置一个状态值或者标志位,它等于多少,匹配上才能访问
                }
                
              3. 重写apply方法;

                @Override
                public GatewayFilter apply(Config config) {
                    
                    return new GatewayFilter() {
                        @Override
                        public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                            ServerHttpRequest request = exchange.getRequest();
                            System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:-->"+config.getStatus());
                            if (request.getQueryParams().containsKey("zm")) {
                                return chain.filter(exchange);
                            }else {
                                exchange.getResponse().setStatusCode(HttpStatus.BAD_GATEWAY);
                                return exchange.getResponse().setComplete();
                            }
                        }
                    };
                }
                
              4. 重写shortcutFieldOrder方法;

                @Override
                public List shortcutFieldOrder() {
                    return Arrays.asList("status");
                }
                
              5. 空参构造方法,内部调用super;

                public MyGatewayFilterFactory(){
                    super(MyGatewayFilterFactory.Config.class);
                }
                
              6. 完整MyGatewayFilterFactory类;

                @Component
                public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory {
                    public MyGatewayFilterFactory(){
                        super(MyGatewayFilterFactory.Config.class);
                    }
                    @Override
                    public GatewayFilter apply(Config config) {
                        
                        return new GatewayFilter() {
                            @Override
                            public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                                ServerHttpRequest request = exchange.getRequest();
                                System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:-->"+config.getStatus());
                                if (request.getQueryParams().containsKey("zm")) {
                                    return chain.filter(exchange);
                                }else {
                                    exchange.getResponse().setStatusCode(HttpStatus.BAD_GATEWAY);
                                    return exchange.getResponse().setComplete();
                                }
                            }
                        };
                    }
                    @Override
                    public List shortcutFieldOrder() {
                        return Arrays.asList("status");
                    }
                    public static class Config{
                        @Getter@Setter
                        private String status;//设置一个状态值或者标志位,它等于多少,匹配上才能访问
                    }
                }
                
              7. 全局配置文件中配置yml;

                - id: pay_routh3
                  uri: lb://cloud-payment-service
                  predicates:
                     - Path=/pay/gateway/filter/**
                   # - Path=/gateway/filter/**    #实际上你应该在浏览器输入http://localhost:9527/gateway/filter
                     #- Path=/ZM/abcd/{segment}  #修改访问路径,{segment}占位符的内容会和SetPath的{segment}保持一致
                  filters:
                     -  My=zm #自定义的过滤器
                
              8. 重启9527测试

                先还按照原来的不带任何参数看能不能访问

                Gateway新一代网关,Gateway新一代智能网关 第67张

                当然不能访问,然后添加参数的,参数的value是什么我们就没有做限制随便。

                Gateway新一代网关,Gateway新一代智能网关 第68张

                带着我们设置的参数就可以访问了。


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码