• 微服务之网关路由


    一、概述

    1.1认识网关

    什么是网关?

    顾明思议,网关就是络的口。数据在网络间传输,从一个网络传输到另一网络时就需要经过网关来做数据的路由和转发以及数据安全的校验

    更通俗的来讲,网关就像是以前园区传达室的大爷。

    • 外面的人要想进入园区,必须经过大爷的认可,如果你是不怀好意的人,肯定被直接拦截。

    • 外面的人要传话或送信,要找大爷。大爷帮你带给目标人。

    现在,微服务网关就起到同样的作用。前端请求不能直接访问微服务,而是要请求网关:

    • 网关可以做安全控制,也就是登录身份校验,校验通过才放行

    • 通过认证后,网关再根据请求判断应该访问哪个微服务,将请求转发过去

     1.2SpringCloudGateway概述

    Gateway是在Spring生态系统之上构建的API网关服务,基于Spring6,Spring Boot 3和Project Reactor等技术。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式,并为它们提供跨领域的关注点,例如:安全性、监控/度量和恢复能力。

    在SpringCloud当中,提供了两种网关实现方案:

    • Netflix Zuul:早期实现,目前已经淘汰

    • SpringCloudGateway:基于Spring的WebFlux技术,完全支持响应式编程,吞吐能力更强

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

    1.3Gateway核心介绍

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

    Route(路由)

    路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过虑器组成,如果断言为true则匹配该路由

    Predicate(断言)

    参考的是Java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由

    Filter(过滤)

    指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

    • 在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;
    • 在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

    总结

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

    predicate就是我们的匹配条件;

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

    二、快速入门

    接下来,我们先看下如何利用网关实现请求路由。由于网关本身也是一个独立的微服务,因此也需要创建一个模块开发功能。大概步骤如下:

    • 创建网关微服务

    • 引入SpringCloudGateway、NacosDiscovery依赖

    • 编写启动类

    • 配置网关路由

    .创建项目

    pom依赖

    1. org.springframework.cloud
    2. spring-cloud-starter-gateway
    3. org.springframework.cloud
    4. spring-cloud-starter-consul-discovery
    5. org.springframework.boot
    6. spring-boot-starter-actuator

    yml配置

    1. server:
    2. port: 9527
    3. spring:
    4. application:
    5. name: cloud-gateway #以微服务注册进consul或nacos服务列表内
    6. cloud:
    7. consul: #配置consul地址
    8. host: localhost
    9. port: 8500
    10. discovery:
    11. prefer-ip-address: true
    12. service-name: ${spring.application.name}
    13. gateway:
    14. routes:
    15. - id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    16. uri: http://localhost:8001 #匹配后提供服务的路由地址
    17. predicates:
    18. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    19. - id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    20. uri: http://localhost:8001 #匹配后提供服务的路由地址
    21. predicates:
    22. - Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由

    启动类

    1. @SpringBootApplication
    2. @EnableDiscoveryClient //服务注册和发现
    3. public class Main9527
    4. {
    5. public static void main(String[] args)
    6. {
    7. SpringApplication.run(Main9527.class,args);
    8. }
    9. }

    测试

    1. @RestController
    2. public class PayGateWayController
    3. {
    4. @Resource
    5. PayService payService;
    6. @GetMapping(value = "/pay/gateway/get/{id}")
    7. public ResultData getById(@PathVariable("id") Integer id)
    8. {
    9. Pay pay = payService.getById(id);
    10. return ResultData.success(pay);
    11. }
    12. @GetMapping(value = "/pay/gateway/info")
    13. public ResultData getGatewayInfo()
    14. {
    15. return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
    16. }
    17. }

    配置

    相同公司

    1. @FeignClient(value = "cloud-payment-service")//自己人内部,自己访问自己,写微服务名字OK
    2. public interface PayFeignApi
    3. {
    4. /**
    5. * GateWay进行网关测试案例01
    6. * @param id
    7. * @return
    8. */
    9. @GetMapping(value = "/pay/gateway/get/{id}")
    10. public ResultData getById(@PathVariable("id") Integer id);
    11. /**
    12. * GateWay进行网关测试案例02
    13. * @return
    14. */
    15. @GetMapping(value = "/pay/gateway/info")
    16. public ResultData getGatewayInfo();
    17. }

    不同公司

    存在ym配置,映射写死问题

    三、GateWay高级特性

    3.1Route以微服务名-动态获取服务URI

    1. gateway:
    2. routes:
    3. - id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    4. #uri: http://localhost:8001 #匹配后提供服务的路由地址
    5. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    6. predicates:
    7. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    8. - id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    9. #uri: http://localhost:8001 #匹配后提供服务的路由地址
    10. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    11. predicates:
    12. - Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由

    3.2Predicate断言(谓词)

    整体架构

    两种配置方式

     Shortcut Configuration

     After Route Predicate

    获取datatime

    1. public class ZonedDateTimeDemo
    2. {
    3. public static void main(String[] args)
    4. {
    5. ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
    6. System.out.println(zbj);
    7. }
    8. }

    yml配置

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. - After=2024-4-16T14:37:50.586918800+08:00[Asia/Shanghai]

    Before Route Predicate

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-11-27T15:25:06.424566300+08:00[Asia/Shanghai] #超过规定时间不可访问

    Between Route Predicate

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. #- Before=2023-11-20T17:58:13.586918800+08:00[Asia/Shanghai]
    5. - Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]

    Cookie Route Predicate

    Cookie Route Predicate需要两个参数,一个是 Cookie name ,一个是正则表达式。

    路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. - Cookie=username,zzyy

    Header Route Predicate

    两个参数:一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. #- Cookie=username,zzyy
    7. - Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式

    Host Route Predicate

    Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. #- Cookie=username,zzyy
    7. #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
    8. - Host=**.atguigu.com

    Path Route Predicate

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. #- Cookie=username,zzyy
    7. #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
    8. - Host=**.atguigu.com

    Query Route Predicate

    支持传入两个参数,一个是属性名,一个为属性值,属性值可以是正则表达式。

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. #- Cookie=username,zzyy
    7. #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
    8. #- Host=**.atguigu.com
    9. - Query=username, \d+ # 要有参数名username并且值还要是整数才能路由

    RemoteAddr route predicate

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. #- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
    4. - Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
    5. #- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
    6. #- Cookie=username,zzyy
    7. #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
    8. #- Host=**.atguigu.com
    9. #- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
    10. - RemoteAddr=192.168.124.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。

    Method Route Predicate

    配置某个清求地址,只能用Get/Post方法访问,方法限制

    总结

    1. server:
    2. port: 9527
    3. spring:
    4. application:
    5. name: cloud-gateway #以微服务注册进consul或nacos服务列表内
    6. cloud:
    7. consul: #配置consul地址
    8. host: localhost
    9. port: 8500
    10. discovery:
    11. prefer-ip-address: true
    12. service-name: ${spring.application.name}
    13. gateway:
    14. routes:
    15. - id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    16. #uri: http://localhost:8001 #匹配后提供服务的路由地址
    17. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    18. predicates:
    19. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    20. - After=2023-12-30T23:02:39.079979400+08:00[Asia/Shanghai]
    21. #- Cookie=username,zzyy
    22. # - Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
    23. #- Host=**.atguigu.com
    24. #- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
    25. #- RemoteAddr=192.168.124.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
    26. - id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    27. #uri: http://localhost:8001 #匹配后提供服务的路由地址
    28. uri: lb://cloud-payment-service
    29. predicates:
    30. - Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由

    3.3自定义断言

    开头任意取名,但是必须以RoutePredicateFactory后缀结尾


    1.新建类名XXX需要以RoutePredicateFactory结尾并继承AbstractRoutePredicateFactory类

    1. @Component标注不可忘
    2. public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory
    3. {
    4. }

    2.重写appy方法

    1. @Override
    2. public Predicate apply(MyRoutePredicateFactory.Config config)
    3. {
    4. return null;
    5. }

    3.新建apply方法所需要的静态内部类MyRoutePredicateFactory.Config这个Config类就是我们的路由断言规侧,重要

    1. @Validated
    2. public static class Config{
    3. @Setter
    4. @Getter
    5. @NotEmpty
    6. private String userType; //钻、金、银等用户等级
    7. }

    4.空参构造方法,内部调用super

    1. public MyRoutePredicateFactory()
    2. {
    3. super(MyRoutePredicateFactory.Config.class);
    4. }

    5.重写apply方法第二版

    1. @Override
    2. public Predicate apply(MyRoutePredicateFactory.Config config)
    3. {
    4. return new Predicate()
    5. {
    6. @Override
    7. public boolean test(ServerWebExchange serverWebExchange)
    8. {
    9. //检查request的参数里面,userType是否为指定的值,符合配置就通过
    10. String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
    11. if (userType == null) return false;
    12. //如果说参数存在,就和config的数据进行比较
    13. if(userType.equals(config.getUserType())) {
    14. return true;
    15. }
    16. return false;
    17. }
    18. };
    19. }

     完整

    1. // 使用@Component注解,将该类声明为一个Spring组件
    2. @Component
    3. // 继承AbstractRoutePredicateFactory类,并指定泛型参数为Config类
    4. public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {
    5. // 构造函数,调用父类的构造函数,传入Config类的类型
    6. public MyRoutePredicateFactory() {
    7. super(MyRoutePredicateFactory.Config.class);
    8. }
    9. // 定义一个静态内部类Config,用于存储配置信息
    10. @Validated
    11. public static class Config {
    12. @Setter
    13. @Getter
    14. @NotEmpty
    15. private String userType; // 用户等级,如钻、金、银等
    16. }
    17. // 重写apply方法,接收一个Config类型的参数,返回一个Predicate对象
    18. @Override
    19. public Predicate apply(MyRoutePredicateFactory.Config config) {
    20. // 返回一个新的Predicate对象
    21. return new Predicate() {
    22. // 重写test方法,接收一个ServerWebExchange类型的参数
    23. @Override
    24. public boolean test(ServerWebExchange serverWebExchange) {
    25. // 从请求中获取userType参数的值
    26. String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
    27. // 如果userType为空,则返回false
    28. if (userType == null) return false;
    29. // 如果userType与config中的userType相等,则返回true
    30. if (userType.equals(config.getUserType())) {
    31. return true;
    32. }
    33. // 其他情况返回false
    34. return false;
    35. }
    36. };
    37. }
    38. }

    yml配置

    1. predicates:
    2. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    3. - After=2024-04-16T14:43:38.193234700+08:00[Asia/Shanghai]
    4. # - My=diamond
    5. - name: My
    6. args:
    7. userType: diamond

    短处配置

    1. @Override
    2. public List shortcutFieldOrder() {
    3. return Collections.singletonList("userType");
    4. }

    3.4Filteri过滤

    pre"和“post”分别会在请求被执行前调用和被执行后调用用来修改请求和响应信息

    功能:

    • 请求鉴权
    • 异常处理
    • 记录接口调用时长统计,重点,大厂面试设计题

     全局默认过滤器Global Filters

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

    单一内置讨虑器GatewavFilter

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

    自定义过滤器

    3.5请求头(RequestHeader)相关组

    The AddRequestHeader GatewayFilter Factory】

    指定请求头

    测试类

    1. @GetMapping(value = "/pay/gateway/filter")
    2. public ResultData getGatewayFilter(HttpServletRequest request)
    3. {
    4. String result = "";
    5. Enumeration headers = request.getHeaderNames();
    6. while(headers.hasMoreElements())
    7. {
    8. String headName = headers.nextElement();
    9. String headValue = request.getHeader(headName);
    10. System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
    11. if(headName.equalsIgnoreCase("X-Request-atguigu1")
    12. || headName.equalsIgnoreCase("X-Request-atguigu2")) {
    13. result = result+headName + "\t " + headValue +" ";
    14. }
    15. }
    16. return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
    17. }

    yml配置

    1. - id: pay_routh3 #pay_routh3
    2. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    3. predicates:
    4. - Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由
    5. filters:
    6. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
    7. - AddRequestHeader=X-Request-atguigu2,atguiguValue2

    The RemoveRequestHeader GatewayFilter Factory yml配置

    删除请求头ByName

    1. filters:
    2. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
    3. - AddRequestHeader=X-Request-atguigu2,atguiguValue2
    4. - RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site

    The SetRequestHeader GatewayFilter Factory

    修改请求头ByName

    1. filters:
    2. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
    3. - AddRequestHeader=X-Request-atguigu2,atguiguValue2
    4. - RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
    5. - SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy

    3.6请求参数(RequestParameter)相关组

    • The AddRequestParameter GatewayFilter Factory
    • The RemoveRequestParameter GatewayFilter Factory

    3.7回应头(ResponseHeader)相关组

    1. - AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
    2. - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
    3. - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除

    3.8前缀和路径相关组(重要)

    The PrefixPath GatewayFilter Factory

    • 自动添加路径前缀
    1. predicates:
    2. #- Path=/pay/gateway/filter/** # 被分拆为: PrefixPath + Path
    3. - Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
    4. filters:
    5. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
    6. #- AddRequestHeader=X-Request-atguigu2,atguiguValue2
    7. #- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
    8. #- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
    9. #- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
    10. #- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
    11. #- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
    12. #- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
    13. #- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
    14. - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter

    The SetPath GatewayFilter Factory

    • 访问路径修改
    1. predicates:
    2. #- Path=/pay/gateway/filter/** # 真实地址
    3. #- Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
    4. - Path=/XYZ/abc/{segment} # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
    5. filters:
    6. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
    7. #- AddRequestHeader=X-Request-atguigu2,atguiguValue2
    8. #- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
    9. #- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
    10. #- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
    11. #- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
    12. #- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
    13. #- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
    14. #- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
    15. #- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
    16. - SetPath=/pay/gateway/{segment} # {segment}表示占位符,你写abc也行但要上下一致

    The RedirectTo GatewayFilter Factory

    • 重定向到某个页面
       
    1. predicates:
    2. - Path=/pay/gateway/filter/** # 真实地址
    3. #- Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
    4. #- Path=/XYZ/abc/{segment} # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
    5. filters:
    6. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
    7. #- AddRequestHeader=X-Request-atguigu2,atguiguValue2
    8. #- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
    9. #- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
    10. #- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
    11. #- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
    12. #- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
    13. #- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
    14. #- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
    15. #- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
    16. - RedirectTo=302, http://www.atguigu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.atguigu.com/

    3.9Default Filters

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

    3.10自定义全局Filter

    1. @Component //不要忘记
    2. @Slf4j
    3. public class MyGlobalFilter implements GlobalFilter, Ordered
    4. {
    5. @Override
    6. public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain)
    7. {
    8. return null;
    9. }
    10. @Override
    11. public int getOrder()
    12. {
    13. return 0;
    14. }
    15. }

    yml配置

    1. server:
    2. port: 9527
    3. spring:
    4. application:
    5. name: cloud-gateway #以微服务注册进consul或nacos服务列表内
    6. cloud:
    7. consul: #配置consul地址
    8. host: localhost
    9. port: 8500
    10. discovery:
    11. prefer-ip-address: true
    12. service-name: ${spring.application.name}
    13. gateway:
    14. routes:
    15. - id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    16. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    17. predicates:
    18. - Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
    19. - After=2023-12-30T23:02:39.079979400+08:00[Asia/Shanghai]
    20. - id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
    21. uri: lb://cloud-payment-service
    22. predicates:
    23. - Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由
    24. - id: pay_routh3 #pay_routh3
    25. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
    26. predicates:
    27. - Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由,默认正确地址
    28. filters:
    29. - AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
    1. @Component
    2. @Slf4j
    3. public class MyGlobalFilter implements GlobalFilter, Ordered
    4. {
    5. /**
    6. * 数字越小优先级越高
    7. * @return
    8. */
    9. @Override
    10. public int getOrder()
    11. {
    12. return 0;
    13. }
    14. private static final String BEGIN_VISIT_TIME = "begin_visit_time";//开始访问时间
    15. /**
    16. *第2版,各种统计
    17. * @param exchange
    18. * @param chain
    19. * @return
    20. */
    21. @Override
    22. public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    23. //先记录下访问接口的开始时间
    24. exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());
    25. return chain.filter(exchange).then(Mono.fromRunnable(()->{
    26. Long beginVisitTime = exchange.getAttribute(BEGIN_VISIT_TIME);
    27. if (beginVisitTime != null){
    28. log.info("访问接口主机: " + exchange.getRequest().getURI().getHost());
    29. log.info("访问接口端口: " + exchange.getRequest().getURI().getPort());
    30. log.info("访问接口URL: " + exchange.getRequest().getURI().getPath());
    31. log.info("访问接口URL参数: " + exchange.getRequest().getURI().getRawQuery());
    32. log.info("访问接口时长: " + (System.currentTimeMillis() - beginVisitTime) + "ms");
    33. log.info("我是美丽分割线: ###################################################");
    34. System.out.println();
    35. }
    36. }));
    37. }
    38. }

    3.11自定义条件Filter

    省略

  • 相关阅读:
    新库上线 | CnOpenData 新三板公司专利及引用被引用数据
    【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)
    C/C++笔试易错与高频题型&图解知识点(二)—— C++部分(持续更新中)
    新手必会的静态站点生成器——Gridsome
    阿里云短信验证接口调用
    【编译原理+句柄+入栈顺序从右至左+系统调用+win api+程序安排+acm ieee usenix信息】答疑
    WireGuard 组网教程:快速构建安全高效的私密网络并实现内网穿透
    基于Spring Boot的自习室预定系统的设计与实现
    初步观察UE蓝图的“Branch节点”,这个最简单的K2Node的代码
    软件工程理论与实践 (吕云翔) 第十三章 软件测试方法与过程课后习题及其答案解析
  • 原文地址:https://blog.csdn.net/qq_62377885/article/details/137807582