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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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 {@ResourcePayService 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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 {@Resourceprivate 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Cookie=mycookie,mycookievalue

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

充分展开配置

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

应用程序.yml

spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- name: Cookieargs:name: mycookieregexp: 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_routeuri: https://example.orgpredicates:- 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Cookie=chocolate, ch.p

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Header=X-Request-Id, \d+

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Host=**.somehost.org,**.anotherhost.org

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Method=GET,POST

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Path=/red/{segment},/blue/{segment}

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routeuri: https://example.orgpredicates:- Query=green

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_highuri: https://weighthigh.orgpredicates:- Weight=group1, 8- id: weight_lowuri: https://weightlow.orgpredicates:- Weight=group1, 2

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

修改9527YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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> {@Overridepublic 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> {@Overridepublic Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {return null;}@Validatedpublic static class Config {@Getter@Setter@NotEmptyprivate 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);}@Overridepublic Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {return null;}@Validatedpublic static class Config {@Getter@Setter@NotEmptyprivate 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);}@Overridepublic Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {return new Predicate<ServerWebExchange>() {@Overridepublic 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;}};}@Validatedpublic static class Config {@Getter@Setter@NotEmptyprivate 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使其支持短格式写法@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("userType");}public MyRoutePredicateFactory() {super(Config.class);}@Overridepublic Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {return new Predicate<ServerWebExchange>() {@Overridepublic 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;}};}@Validatedpublic static class Config {@Getter@Setter@NotEmptyprivate String userType;}
}
7:配置yml
server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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 {@ResourcePayService 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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 {@ResourcePayService 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: lb://cloud-payment-service                #匹配后提供服务的路由地址predicates:# - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由- Path=/gateway/filter/**   # 断言,为配合PrefixPath测试过滤,暂时注释掉/payfilters:- 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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 {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return null;}@Overridepublic int getOrder() {return 0;}
}

(2)修改YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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";@Overridepublic 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();}}));}/**** 数字越小优先级越高**/@Overridepublic 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@Getterprivate 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> {@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic 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@Getterprivate 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> {@Overridepublic List<String> shortcutFieldOrder() {List<String> list = new ArrayList<String>();list.add("status");return list;}@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic 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@Getterprivate 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);}@Overridepublic List<String> shortcutFieldOrder() {List<String> list = new ArrayList<String>();list.add("status");return list;}@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic 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@Getterprivate String status;}
}

(6)配置YML

server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: trueservice-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_routh3uri: 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.rhkb.cn/news/478166.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis基本使用

一、向SQL语句传参: 1.MyBatis日志输出配置: mybatis配置文件设计标签和顶层结构如下: 可以在mybatis的配置文件使用settings标签设置&#xff0c;输出运过程SQL日志,通过查看日志&#xff0c;可以判定#{}和${}的输出效果 settings设置项: logImpl指定 MyBatis 所用日志的具…

实验二 系统响应及系统稳定性

实验目的 &#xff08;1&#xff09;学会运用Matlab 求解离散时间系统的零状态响应&#xff1b; &#xff08;2&#xff09;学会运用Matlab 求解离散时间系统的单位取样响应&#xff1b; &#xff08;3&#xff09;学会运用Matlab 求解离散时间系统的卷积和。 实验原理及实…

秋招面试基础总结,Java八股文基础(串联知识),四万字大全

目录 值传递和引用传递 静态变量和静态代码块的执行顺序 Java​​​​​​​集合的框架&#xff0c;Set,HashSet,LinkedHashSet这三个底层是什么 多线程篇 Java实现多线程的方式 假设一个线程池&#xff0c;核心线程数是2&#xff0c;最大线程数是3&#xff0c;阻塞队列是4…

C# 数据结构之【图】C#图

1. 图的概念 图是一种重要的数据结构&#xff0c;用于表示节点&#xff08;顶点&#xff09;之间的关系。图由一组顶点和连接这些顶点的边组成。图可以是有向的&#xff08;边有方向&#xff09;或无向的&#xff08;边没有方向&#xff09;&#xff0c;可以是加权的&#xff…

如何在WPF中嵌入其它程序

在WPF中嵌入其它程序&#xff0c;这里提供两种方案 一、使用WindowsFormHost 使用步骤如下 1、添加WindowsFormsIntegration和System.Windows.Forms引用 2、在界面上放置WindowsFormHost和System.Windows.Forms.Panel 1 <Grid> 2 <WindowsFormsHost> 3…

丹摩|丹摩智算平台深度评测

1. 丹摩智算平台介绍 随着人工智能和大数据技术的快速发展&#xff0c;越来越多的智能计算平台涌现&#xff0c;为科研工作者和开发者提供高性能计算资源。丹摩智算平台作为其中的一员&#xff0c;定位于智能计算服务的提供者&#xff0c;支持从数据处理到模型训练的全流程操作…

[pdf,epub]162页《分析模式》漫谈合集01-35提供下载

《分析模式》漫谈合集01-35的pdf、epub文件&#xff0c;已上传至本号的CSDN资源。 如果CSDN资源下载有问题&#xff0c;可到umlchina.com/url/ap.html。 已排版成适合手机阅读&#xff0c;pdf的排版更好一些。 ★UMLChina为什么叒要翻译《分析模式》&#xff1f; ★[缝合故事…

Charles抓包工具-笔记

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

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

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

WebRTC音视频同步原理与实现详解(上)

第一章、RTP时间戳与NTP时间戳 1.1 RTP时间戳 时间戳&#xff0c;用来定义媒体负载数据的采样时刻&#xff0c;从单调线性递增的时钟中获取&#xff0c;时钟的精度由 RTP 负载数据的采样频率决定。 音频和视频的采样频率是不一样的&#xff0c;一般音频的采样频率有 8KHz、…

uni-app 发布媒介功能(自由选择媒介类型的内容) 设计

1.首先明确需求 我想做一个可以选择媒介的内容&#xff0c;来进行发布媒介的功能 &#xff08;媒介包含&#xff1a;图片、文本、视频&#xff09; 2.原型设计 发布-编辑界面 通过点击下方的加号&#xff0c;可以自由选择添加的媒介类型 但是因为预览中无法看到视频的效果&…

详细探索xinput1_3.dll:功能、问题与xinput1_3.dll丢失的解决方案

本文旨在深入探讨xinput1_3.dll这一动态链接库文件。首先介绍其在计算机系统中的功能和作用&#xff0c;特别是在游戏和输入设备交互方面的重要性。然后分析在使用过程中可能出现的诸如文件丢失、版本不兼容等问题&#xff0c;并提出相应的解决方案&#xff0c;包括重新安装相关…

Ubuntu,openEuler,MySql安装

文章目录 Ubuntu什么是Ubuntu概述Ubuntu版本简介桌面版服务器版 部署系统新建虚拟机安装系统部署后的设置设置root密码关闭防火墙启用允许root进行ssh安装所需软件制作快照 网络配置Netplan概述配置详解配置文件DHCP静态IP设置 软件安装方法apt安装软件作用常用命令配置apt源 d…

大数据实验4-HBase

一、实验目的 阐述HBase在Hadoop体系结构中的角色&#xff1b;能够掌握HBase的安装和配置方法熟练使用HBase操作常用的Shell命令&#xff1b; 二、实验要求 学习HBase的安装步骤&#xff0c;并掌握HBase的基本操作命令的使用&#xff1b; 三、实验平台 操作系统&#xff1…

docker pull命令拉取镜像失败的解决方案

docker pull命令拉取镜像失败的解决方案 简介&#xff1a; docker pull命令拉取镜像失败的解决方案 docker pull命令拉取镜像失败的解决方案 一、执行docker pull命令&#xff0c;拉取镜像失败 报错信息&#xff1a;error pulling image configuration: Get https://produc…

qt+opengl 三维物体加入摄像机

1 在前几期的文章中&#xff0c;我们已经实现了三维正方体的显示了&#xff0c;那我们来实现让物体的由远及近&#xff0c;和由近及远。这里我们需要了解一个概念摄像机。 1.1 摄像机定义&#xff1a;在世界空间中位置、观察方向、指向右侧向量、指向上方的向量。如下图所示: …

安宝特方案 | AR助力紧急救援,科技守卫生命每一刻!

在生死时速的紧急救援战场上&#xff0c;每一秒都至关重要&#xff01;随着科技的发展&#xff0c;增强现实&#xff08;AR&#xff09;技术正在逐步渗透到医疗健康领域&#xff0c;改变着传统的医疗服务模式。 安宝特AR远程协助解决方案&#xff0c;凭借其先进的技术支持和创新…

生成对抗网络模拟缺失数据,辅助PAMAP2数据集仿真实验

PAMAP2数据集是一个包含丰富身体活动信息的数据集&#xff0c;它为我们提供了一个理想的平台来开发和测试HAR模型。本文将从数据集的基本介绍开始&#xff0c;逐步引导大家通过数据分割、预处理、模型训练&#xff0c;到最终的性能评估&#xff0c;在接下来的章节中&#xff0c…

使用ChatGPT生成和优化电子商务用户需求规格说明书

在电子商务项目开发中&#xff0c;用户需求规格说明书&#xff08;User Requirement Specification, URS&#xff09;是团队沟通与项目成功的基石。然而&#xff0c;面对复杂多变的需求&#xff0c;如何快速生成清晰、完整且具备说服力的文档&#xff1f;这正是AI工具的用武之地…

12-表的约束

知识背景 表的约束&#xff0c;就是在表中的数据上加上约束&#xff0c;也被称为数据完整性约束。数据完整性约束的目的是为了不被规定的、不符合规范的数据进入数据库 在录入数据库或数据发生变化时&#xff0c;DBMS(数据库管理系统)会按照一定的约束条件对数据进行监测&…