09.Gateway新一代网关

news/2025/1/10 20:07:48/文章来源:https://www.cnblogs.com/changming06/p/18522378

1.概述

1.1 是什么

1.1.1 官网

https://docs.spring.io/spring-cloud-gateway/reference/

1.1.2 体系定位

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关SpringCloud Gateway替代Zuul。一句话:gateway是原zuul1.x版的替代。

1.2 项目中的网关的定位

1.3 能干吗

反向代理,鉴权,流量控制,熔断,日志控制等。

1.4 总结

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

2.Gateway三大核心

2.1 概述

2.2 Route(路由)

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

2.3 Predicate(断言)

断言参考的是Java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的内容(请求头或请求参数),请求符合断言,进行路由。

2.4 Filter(过滤)

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

2.5 总结

http请求,到网关后,会先匹配是否有这个路由,有则进行断言,成功则经过过滤,转发到对应的微服务实例,进行后续的业务处理。不存在请求路由,或断言失败都无法,进行请求转发。

3.Gateway工作流程

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

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

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

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

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

4.入门配置

4.1 建module

cloud-gateway9527

4.2 改pom

一般Spring官网对于该组件的说明文档,都会有标识,该组件的maven坐标。

To include Spring Cloud Gateway in your project, use the starter with a group ID of org.springframework.cloud and an artifact ID of spring-cloud-starter-gateway. See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.

<!--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>

4.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.4 主启动

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

4.5 业务类

无,网关无任何业务代码。

4.6 启动

启动consul和gateway,会发现,在Consul(http://localhost:8500)中有,cloud-gateway实例。

5.网关如何做路由映射

5.1 诉求

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

5.2 8001服务,新建PayGateWayController

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

5.3 启动8001,测试

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

5.5 重启9527

启动consul,8001,Gateway9527。

访问说明

添加网关前http://localhost:8001/pay/gateway/get/1

添加网关后http://localhost:9527/pay/gateway/get/1

隐真示假

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

证明,在8001支付微服务前在Gateway成功。但是注意这是,从外部访问时会走网关。

5.6 启动80订单微服务测试

5.6.1 修改cloud-api-commons的PayFeignApi接口
    /*** GateWay进行网关测试案例01* @param id* @return*/@GetMapping(value = "/pay/gateway/get/{id}")ResultData getById(@PathVariable("id") Integer id);/*** GateWay进行网关测试案例02* @return*/@GetMapping(value = "/pay/gateway/info")ResultData<String> getGatewayInfo();
5.6.2 修改cloud-comsumer-feign-order80模块

新增OrderGateWayController

package com.atguigu.cloud.controller;import com.atguigu.cloud.apis.PayFeignApi;
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;@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.6.3 启动cloud-comsumer-feign-order80

访问http://localhost:8080/feign/pay/gateway/get/1

测试发现,gateway启动与否,都能获取到数据。

原因, 是因为PayFeignApi,配置的直接访问的8001的实例。不会走网关。因为80模块,是在服务系统的内部调用内部的微服务,不需要再走网关,多次一举,网关是对外部请求的一种分发和限制。也可以将其改成cloud-gateway服务,来测试网关效果,略。

@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {...
}

5.7 存在问题

上述yml配置,路由的地址,是写死的,其他服务一改端口号,配置失效了。

6.Gateway高级特性

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

6.1.1 存在问题

见上述5.7。

6.1.2 解决方式
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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由
6.1.3测试

测试,cloud-payment-service服务,修改端口号,都可以访问成功。

6.2 Predicate(断言)

6.2.1 是什么

官网

https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/request-predicates-factories.html


Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。

Spring Cloud Gateway内置许多Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合。

Spring Cloud Gateway创建Route对象时,使用RouterPredicateFactory创建Predicate对象,该对象赋给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories。所有这些谓词都匹配HTTP请求的不同属性,多种谓词工厂可以组合,并通过逻辑and

6.3 启动gateway查看日志

6.4 整体架构

6.5 常用的内置Route Predicate

6.5.1 配置语法总体概述

6.5.2 Shortcut Configuration

6.5.3 Fully Expanded Arguments

6.5.4 测试地址

http://localhost:9527/pay/gateway/get/1

6.5.5 AfterRoutePredicate使用

官网例子

注意,After=后面跟的是ZonedDateTime类生成的时间字符串,需要ZonedDateTime生成。

public class ZonedDateTimeDemo{public static void main(String[] args){ZonedDateTime zdt = ZonedDateTime.now(); // 默认时区System.out.println(zdt);}
}

实际配置

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #在指定时间之后- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.6 BeforeRoutePredicate

和AfterRoutePredicate类似,只是作用在指定时间之前,略。

6.5.7 BetweenRoutePredicateFactory

和之前类似,略

6.5.8 CookieRoutePredicate

官网例子

cookie的值,支持使用正则表达式。

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]- Cookie=username,br.+x 	#Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.9 HeaderRoutePredicate

官网示例

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.10 HostRoutePredicate

官网示例

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式- Host=**.atguigu.com- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.11 PathRoutePredicate

一直就有该配置,略

- Path=/pay/gateway/get/** 
6.5.12 QueryRoutePredicate

官网示例

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.13 RemoteAddrRoutePredicate

官网示例

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com#- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由- RemoteAddr=192.168.1.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是CIDR表示法。- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

CIDR表示法

CIDR(Classless Inter-Domain Routing),无类别域间路由是一个用于给用户分配IP地址以及在互联网上有效地路由IP数据包的对IP地址进行归类的方法。

简略说,给一个举例的ip/count,客户端请求的ip地址,从左到右,count个要和举例的ip相同,才成功。

测试

6.5.14 MethodRoutePredicate

官网示例

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com#- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由#- RemoteAddr=192.168.1.7/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。- Method=GET,POST- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

测试

6.5.15 总结

上述内置的Predicate,就是对请求,进行限制,满足限制通过,不满足,返回404。

6.6 自定义断言

类名,和自定义的保持一致XxxRoutePredicateFactory

6.6.1 扩展

扩展某些接口,或实现某些抽象类时,最简单,也最有效的方式,就是借鉴别人写好的示例。

这里,直接根据AfterRoutePredicateFactory类,作为模板,进行自定义。

6.6.2 完整代码
package com.atguigu.cloud.mygateway;import jakarta.validation.constraints.NotNull;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {public static final String USER_TYPE = "userType";public MyRoutePredicateFactory() {super(Config.class);}/** 支持Shortcut Configuration配置的方法 */@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList(USER_TYPE);}public static class Config {@NotNullprivate String userType;public String getUserType() {return userType;}public void setUserType(String userType) {this.userType = userType;}}@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");if (userType == null) return false;return userType.equals(config.getUserType());}@Overridepublic Object getConfig() {return config;}@Overridepublic String toString() {return String.format("UserType: %s", config.getUserType());}};}
}
6.6.3 YML

这也是,为什么要类名要求是XxxRoutePredicateFactory

- My=gold
6.6.4 测试

6.7 Filter(过滤)

6.7.1 官网

https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/gatewayfilter-factories.html

6.7.2 介绍

类似于SpringMVC框架中的Interceptor,和Servlet体系中的Filter。

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

6.7.3 作用

请求鉴权、异常处理、统计接口调用时长等。

6.7.4 类型

有三类

全局默认过滤器Global Filters

全局官网地址

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

单一内置过滤器 Gateway Filter

单一官网介绍地址

此类型过滤器,也被称为网关过滤器,这种过滤器主要是作用于单一路由或者某个路由分组。

自定义过滤器

后续有案例。

6.8 Gateway内置的过滤器

官网

也即是上述分类中的单一内置过滤器GatewayFilter。


路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器的作用域为特定路由。Spring Cloud Gateway包括许多内置的网关过滤器工厂。

从官网,可以看到,有30多个单一过滤器。课程中,只选择了一部分进行讲解。其他未讲到的内置过滤器,可以见Spring官网,都有配置案例,和解释

6.9 常用的内置过滤器

按照在HTTP请求中,所属的模块(请求头,请求参数,响应头,路径,其他),不同分为以下几组

6.9.1 请求头(RequestHeader)相关组

1.AddRequestHeader GatewayFilter Factory

添加请求头内容ByName

8001微服务,PayGateWayController新增接口

代码简单,就是获取请求头,打印,判断是否有特殊的请求头。

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

9527网关YML添加过滤内容

注意以下为新增配置

spring:cloud:gateway:routes:- id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由filters:- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若添加多个请求头,则多写一行设置- AddRequestHeader=X-Request-atguigu2,atguiguValue2

重启9527和8001服务,请求 http://localhost:9527/pay/gateway/filter,会发现8001服务,打印的请求头中,有以下内容,只列举一部分。

请求头名: sec-fetch-site			请求头值: none
请求头名: sec-fetch-mode			请求头值: navigate
请求头名: x-request-atguigu1			请求头值: atguiguValue1
请求头名: x-request-atguigu2			请求头值: atguiguValue2

2.RemoveRequestHeader GatewayFilter Factory

删除请求头ByName

修改Gateway配置前,从上述结果看,是有该请求头的。

修改YML

        - id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由filters:- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若添加多个请求头,则多写一行设置- AddRequestHeader=X-Request-atguigu2,atguiguValue2- RemoveRequestHeader=sec-fetch-site # 新增 删除请求头sec-fetch-site

重启9527和8001,测试,请求 http://localhost:9527/pay/gateway/filter。

结果中,已经不包括sec-fetch-site请求头。

3.SetRequestHeader GatewayFilter Factory

修改请求头ByName

修改GatewayYML前,从AddRequestHeader结果看

请求头名: sec-fetch-mode			请求头值: navigate

修改YML

- SetRequestHeader=sec-fetch-mode,Blue #修改请求头sec-fetch-mode

重启9527和8001,测试,请求http://localhost:9527/pay/gateway/filter。

结果

请求头名: sec-fetch-mode			请求头值: Blue
6.9.2 请求参数(RequestParameter)相关组

1.AddRequestParameter GatewayFilter Factory

2.RemoveRequestParameter GatewayFilter Factory

上述两个,一起配置,测试

YML修改

            - AddRequestParameter=breeze,001 #新增请求参数k,v- RemoveRequestParameter=name #删除url请求参数name

PayGatewayController#getGatewayFilter方法修改

        System.out.println("=============================================");String breeze = request.getParameter("breeze");System.out.println("request Parameter breeze: "+breeze);String name = request.getParameter("name");System.out.println("request Parameter name: "+name);System.out.println("=============================================");

重启测试

1.访问 http://localhost:9527/pay/gateway/filter

=============================================
request Parameter breeze: 001
request Parameter name: null
=============================================

2.访问http://localhost:9527/pay/gateway/filter?breeze=002&name=breeze

注意,AddRequestParameter只是一个兜底的,如果请求的参数中有其添加相同的参数,则此配置无效,使用请求中的自带的。

还有,由于HTTP协议本身对于URL编码的要求,任何非ASCII字符(包括中文字符)都需要经过适当的编码才能正确传输,也就是说,如果想配置请求参数的value,为中文字符,则需要使用URL编码后的值,例如,风对应UTF-8 URL编码的结果为%E9%A3%8E

=============================================
request Parameter breeze: 002 
request Parameter name: null
=============================================
6.9.3 响应头(ResponseHeader)相关组

开启配置前,看一下,http://localhost:9527/pay/gateway/filter 响应的响应头信息。


1.AddResponseHeader GatewayFilter Factory
2.SetResponseHeader GatewayFilter Factory
3.RemoveResponseHeader GatewayFilter Factory

新增YML配置

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

重启,出现中文字符编程乱码的原因,移除了Content-Type 响应头,该响应头用于指示资源的媒体类型,即服务器发送的数据格式。这个头部字段非常重要,因为它告诉客户端(如浏览器)应该如何解析接收到的数据。

6.9.4 前缀和路径相关组

1.PrefixPath GatewayFilter Factory

功能,自动添加路径前缀

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

YML修改

        - id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:#- 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 #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter

分拆,说明

之前完整正确地址: http://localhost:9527/pay/gateway/filter
现在完整组合地址: PrefixPath + Path
实际调用地址: http://localhost:9527/gateway/filter相当于说前缀被过滤器统一管理了。


还有StripPrefix GatewayFilter Factory,用以移除,前缀。

2.SetPath GatewayFilter Factory

访问路径修改

配置

        - id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:#- 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 #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - 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也行但要上下一致

配置说明

/XYZ/abc/ {segment}就是个占位符,等价于SetPath后面指定的{segment}内容

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

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

结果,浏览器,显示请求 url:http://localhost:9527/XYZ/abc/filter 但是,最终请求的地址 http://localhost:9527/pay/gateway/filter

3.RedirectTo GatewayFilter Factory

重定向到某个页面

        - id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名uri: lb://cloud-payment-servicepredicates:- 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 #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - 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, https://www.bilibili.com/video/BV1gW421P7RD # 访问http://localhost:9527/pay/gateway/filter重定向到https://www.bilibili.com/video/BV1gW421P7RD

重启9527,测试,略。

6.9.5 其他

Default Filters


这样配置的,单一条件过滤器,就变成了全局过滤器,适用于所有断言匹配的router。

本次案例,全部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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com#- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由#- RemoteAddr=192.168.1.7/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。#- Method=GET,POST- My=gold- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由- id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- 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 #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - 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, https://www.bilibili.com/video/BV1gW421P7RD # 访问http://localhost:9527/pay/gateway/filter重定向到https://www.bilibili.com/video/BV1gW421P7RD

6.10 Gateway自定义过滤器

6.10.1 自定义全局Filter

面试题,统计接口调用耗时情况

通过自定义全局过滤器搞定上述情况。

自定义全局过滤器,官网

https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/global-filters.html

该页面有案例

编码

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;/*** 记录访问日志的Gateway全局过滤器*/
@Component
public class RecordVisitLogGlobalFilter implements GlobalFilter, Ordered {public static final Logger logger = LoggerFactory.getLogger(RecordVisitLogGlobalFilter.class);public 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) {logger.info("访问接口主机: " + exchange.getRequest().getURI().getHost());logger.info("访问接口端口: " + exchange.getRequest().getURI().getPort());logger.info("访问接口URL: " + exchange.getRequest().getURI().getPath());logger.info("访问接口URL参数: " + exchange.getRequest().getURI().getRawQuery());logger.info("访问接口时长: " + (System.currentTimeMillis() - beginVisitTime) + "ms");logger.info("###################################################");System.out.println();}}));}@Overridepublic int getOrder() {return -1;//设置优先级,值越小优先级越高}
}

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com#- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由#- RemoteAddr=192.168.1.7/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。#- Method=GET,POST#- My=gold- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由- id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- 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 #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - 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, https://www.bilibili.com/video/BV1gW421P7RD # 访问http://localhost:9527/pay/gateway/filter重定向到https://www.bilibili.com/video/BV1gW421P7RD

测试结果

6.10.2 自定义条件过滤器

自定义单一过滤器GatewayFilter

参考Gateway内置的过滤器,比如AddResponseHeaderGatewayFilterFactory,SetResponseHeaderGatewayFilterFactory等。

自定义网关过滤器规则,和自定义断言类似

新建类名要以XxxGatewayFilterFactory,并继承AbstractGatewayFilterFactory类,新建XxxGatewayFilterFactory.Config内部类,重写apply方法,重写shortcutFieldOrder方法等,具体见编码。

编码

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;import java.util.Arrays;
import java.util.List;@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {public MyGatewayFilterFactory() {super(MyGatewayFilterFactory.Config.class);}@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {ServerHttpRequest request = exchange.getRequest();String configStatus = config.getStatus();//配置的值System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:" + configStatus);if (request.getQueryParams().containsKey(configStatus)) {return chain.filter(exchange);} else {exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);return exchange.getResponse().setComplete();}};}public static class Config {private String status;//设置一个状态值,等于多少,才可以访问public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}}/*** 支持Shortcut Configuration配置的方法*/@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("status");}
}

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-servicepredicates:- Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由#- After=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,再之后#- Before=2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai] #时间断言,之前#- Between=2024-10-29T21:06:17.219789300+08:00[Asia/Shanghai],2024-10-30T21:06:17.219789300+08:00[Asia/Shanghai]#- Cookie=username,br.+x #Cookie断言,,前是cookie键名 ,后是值,可以使用正则表达式#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性,并且值为整数的正则表达式#- Host=**.atguigu.com#- Query=username,\d+  # 要有参数名username并且值还要是整数才能路由#- RemoteAddr=192.168.1.7/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。#- Method=GET,POST#- My=gold- id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由- id: pay_routh3 #pay_routh3                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001                #匹配后提供服务的路由地址uri: lb://cloud-payment-servicepredicates:- Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由#- Path=/gateway/filter/**              # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay#- Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代filters:- My=atguigu #这也是为什么自定义的条件过滤器的类型要满足XxxGatewayFilterFactory的原因- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若添加多个请求头,则多写一行设置
#            - AddRequestHeader=X-Request-atguigu2,atguiguValue2
#            - RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
#            - SetRequestHeader=sec-fetch-mode,Blue #修改请求头sec-fetch-mode
#            - AddRequestParameter=breeze,001   #新增请求参数k,v
#            - RemoveRequestParameter=name #删除url请求参数name
#            - AddResponseHeader=X-Response-atguigu,BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#            - 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, https://www.bilibili.com/video/BV1gW421P7RD # 访问http://localhost:9527/pay/gateway/filter重定向到https://www.bilibili.com/video/BV1gW421P7RD

测试结果

http://localhost:9527/pay/gateway/filter 报错状态码400

http://localhost:9527/pay/gateway/filter?atguigu=x 访问成功

7.Gateway整合Sentinel实现容错

见SpringCloud Alibaba章节。

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

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

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

相关文章

考研打开(6)

开局(6) 开始时间 2024-11-02 19:44:58 结束时间 2024-11-02 19:48:42

34. 在排序数组中查找元素的第一个位置和最后一个位置

题目 参考了y总讲的这题 789. 数的范围 自己是这样写的; class Solution { public:vector<int> searchRange(vector<int>& nums, int target) {vector<int> result(2, -1);int l = 0, r = nums.size() - 1;while (l < r){int mid = l + (r - l) / 2;…

Vue全家桶–Pinia状态管理

什么是Pinia呢?Pinia和Vuex的区别如何使用Pinia?

2024秋软工实践 旺仔水饺队 原型设计和UML设计

作业所属课程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13297作业的目标 实现项目的原型设计与概要设计团队名称 旺仔水饺102201140 黎曼 102201138 黄俊瑶102201127 罗永辉 102201130 郑哲浩102202144 傅钰 10…

5.树上问题

在宇宙的尽头,时空掌控着时间与空间的无尽流转。过去、现在与未来的区别只是一种固执己见的幻觉,所有的时空都在他的眼中交织成永恒的现在。树上问题 开题顺序: \(ACH\) \(A\) CF600E Lomsat gelral题解\(B\) CF708C Centroids \(C\) CF1706E Qpwoeirut and Vertices题解\(D…

2024-2025-1 20241425《计算机基础与程序设计》第6周学习总结

2024-2025-1 20241425《计算机基础与程序设计》第6周学习总结 作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计这个作业要求在哪里 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP/homework/13276这个作业的目标 计算机科学概论(第七版)第7章 《C语…

three.js+vue智慧社区web3d数字孪生三维地图

案例效果截图如下:具体案例场景和功能,详见b站视频: https://www.bilibili.com/video/BV1Bb421E7WL/?vd_source=7d4ec9c9275b9c7d16afe9b4625f636c案例场景逻辑代码:<template><div id="whole"><!-- threejs容器 --><div id="three&q…

网易云课堂视频课件课程下载工具,如何在电脑端下载网易云课堂视频课程课件资料到本地?

一. 安装网易云课堂课程下载器 1.获取学无止下载器 https://www.xuewuzhi.cn/study163_downloader 2.下载安装后,然后点击桌面快捷方式运行即可。 注意:杀毒软件可能会阻止外部exe文件运行,并将其当做成病毒,直接添加信任即可,本软件绝对没有木马病毒。 二. 使用说明 1.学…

html结合js设计一个可拍照可录制可下载的摄像头页面

功能如下html文件用户设置样式,代码如下<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Came…

ENSP之AR路由器一直#####的极端情况判断

系统版本,CPU 如下: 故障原因:AR设备一直###### 分析判断:由于是新安装的系统,没有安全软件限制,防火墙也都放行了,其他一切正常。ENSP凡是要通过virtual box调用的设备都出现了###。判断有两种情况,系统版本或者CPU问题。 通过和客户沟通得知,他对CPU进行了超频。…

如何使用Ida Pro和Core Dump文件定位崩溃位置(Linux下无调试符号的进程专享)

我们在嵌入式Linux开发过程中经常会遇到一个问题,就是程序崩溃后不知道具体位置。因为我们发布到生产环境的一般是没有调试符号的(使用strip或编译时加-s参数,CMake生成的编译指令中的-O3也会造成调试符号丢失),毕竟嵌入式的存储都比较有限,肯定是需要剥离调试符号的。另…