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

宠物电商网站模板黑马程序员学费多少钱

宠物电商网站模板,黑马程序员学费多少钱,芜湖市网站建设,建设网站需要购买目录 十一、Gateway新一代网关 1.概述 2.Gateway三大核心 3.工作流程 4.入门配置 5.路由映射 #xff08;1#xff09;8001 外部添加网关 #xff08;2#xff09;服务间调用添加网关 #xff08;3#xff09;存在问题 6.Gateway高级特性 #xff08;1#x…目录 十一、Gateway新一代网关 1.概述 2.Gateway三大核心  3.工作流程 4.入门配置 5.路由映射 18001 外部添加网关 2服务间调用添加网关 3存在问题 6.Gateway高级特性 1Route路由 2Predicate断言谓词 Ⅰ. 介绍 Ⅱ . 配置方法 Ⅲ . 常用的内置 Route Predicate ① After Route Predicate ② Before Route Predicate  ③ Between Route Predicate  ④ Cookie Route Predicate  ⑤ Header Route Predicate ⑥ Host Route Predicate  ⑦ Path Route Predicate ⑧ Query Route Predicate ⑨ RemoteAddr route predicate ⑩ Method Route Predicate  Ⅳ . 自定义断言 ① 前言 ② 编写步骤 ③ 测试 3 Filter过滤 Ⅰ. 介绍 Ⅱ . Gateway内置的过滤器 ① 请求头RequestHeader相关组 ② 请求参数RequestParameter相关组 ③ 回应头ResponseHeader相关组 ④ 前缀和路径相关组 ⑤ 其他Default Filters Ⅲ . Gateway 自定义过滤器  ① 自定义全局过滤器 ② 自定义局部条件过滤器 十一、Gateway新一代网关 1.概述 Gateway是在 Spring 生态系统之上构建的 API 网关服务基于 Spring6Spring Boot 3和 Project Reactor 等技术。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式并为它们提供跨领域的关注点例如安全性、监控/度量和恢复能力。 体系定位: Cloud 全家桶中有个很重要的组件就是网关在 1.x 版本中都是采用的Zuul网关 但在 2.x 版本中zuul 的升级一直跳票SpringCloud 最后自己研发了一个网关 SpringCloud Gateway 替代 Zuul那就是 SpringCloud Gateway 所以gateway 是原 zuul1.x 版的替代 作用 反向代理鉴权流量控制熔断日志监控 总结 Spring Cloud Gateway 组件的核心是一系列的过滤器通过这些过滤器可以将客户端发送的请求转发路由到对应的微服务。 Spring Cloud Gateway 是加在整个微服务最前沿的防火墙和代理器隐藏微服务结点 IP 端口信息从而加强安全保护。 Spring Cloud Gateway本身也是一个微服务需要注册进服务注册中心。 Questionnginx 和 gateway网关 到底有什么区别 网关作为微服务的请求入口也就是客户端的所有请求都会先到达微服务网关在通过网关的路由转发到我们的真实服务。 理论上这就是 nginx 干的活为什么又多一个网关呢 网关可以做非常多的事情比如解决跨域问题过滤请求验证 token 信息接口服务的保护、限流、安全等。也就是说对于每一个微服务如果有一些重复的代码我们完全可以在网关里进行统一处理从而减少代码冗余性。 举个例子假设我们现在需要验证我们的 token 会话信息 对于 gateway网关他是由 java 语言编写的我直接调用后端 java 编写的 api 去连接到 redis 验证即可。 但对于 nginx它是由 c 语言编写的想要直接连接到 redis是需要在中间通过 lua 脚本实现的。对于 java 程序员来说这是十分繁琐的还要学习 lua 脚本。 所以这时候 gateway网关就要比 nginx 方便的多可以帮助开发人员快速上手。 再举个例子比如灰度发布他是需要在中间去连接到我们的 nacos 的 对于 gateway网关本身就是由 java 语言编写的而 nacos 也是由 java 语言编写的所以连接起来就很方便。 但对于 ngnix去连接 nacos就得写 lua 脚本去发送一个 http 请求去连接到 nacos所以还是学习 lua。 所以微服务之间需要做的事情就可以通过网关来实现更加容易快速上手。 如果不是微服务之间的事情nginx 也是可以做到的。而且相比之下由于 nginx 是由 c 语言编写的而 gateway 网关是由 java 编写的java 底层还是通过 c 封装的所以 nginx 性能更强它在处理高并发请求时性能非常优越适合用作前端的负载均衡器和反向代理。 在大多数情况下Spring Gateway 和 Nginx 是可以搭配使用的。使用 Nginx 作为前端的反向代理和负载均衡器负责处理来自外部客户端的请求然后将请求转发到 Spring Gateway。Spring Gateway 再将请求路由到后端的微服务负责微服务之间的复杂路由、限流、安全等功能 总结Nginx 处理高并发、静态资源和边缘服务的流量而 Spring Gateway 处理更复杂的 API 管理和微服务之间的流量。 2.Gateway三大核心  ① Route路由 路由是构建网关的基本模块它由 ID目标 URI一系列的断言和过滤器组成如果断言为true 则匹配该路由 ② Predicate断言 参考的是Java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容例如请求头或请求参数如果请求与断言相匹配则进行路由 ③ Filter过滤 指的是 Spring 框架中 GatewayFilter 的实例使用过滤器可以在请求被路由前或者之后对请求进行修改。 web 前端请求通过一些匹配条件定位到真正的服务节点。并在这个转发过程的前后进行一些精细化控制。 predicate就是我们的匹配条件 filter就可以理解为一个无所不能的拦截器 有了这两个元素再加上目标 uri 就可以实现一个具体的路由了 3.工作流程 核心逻辑路由转发 断言判断 执行过滤器链 客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前Pre或之后Post执行业务逻辑。 在 “pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等 在 “post” 类型的过滤器中可以做响应内容、响应头的修改日志的输出流量监控等有着非常重要的作用。 4.入门配置 步骤 ① 建 modulecloud-gateway9527在 pom 文件中导入依赖 dependencies!--gateway--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!--服务注册发现consul discovery,网关也要注册进服务注册中心统一管控--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-consul-discovery/artifactId/dependency!-- 指标监控健康检查的actuator,网关是响应式编程删除掉spring-boot-starter-web dependency--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build ② 编写 application.yml server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name} ③ 修改主启动类 SpringBootApplication EnableDiscoveryClient //服务注册和发现 public class Main9527 {public static void main(String[] args){SpringApplication.run(Main9527.class,args);} } 注意网关和业务无关所以不写任何业务代码。 ④ 先启动 8500 服务中心 Consul再启动 9527 网关入驻 5.路由映射 18001 外部添加网关 需求我们目前不想暴露 8001 端口希望在 8001 真正的支付微服务外面套一层 9527 网关 让前端不会直接访问 8001而是先访问 9527 准备 ① 8001 新建 PayGateWayController RestController public class PayGateWayController {ResourcePayService payService;GetMapping(value /pay/gateway/get/{id})public ResultDataPay getById(PathVariable(id) Integer id){Pay pay payService.getById(id);return ResultData.success(pay);}GetMapping(value /pay/gateway/info)public ResultDataString getGatewayInfo(){return ResultData.success(gateway info test IdUtil.simpleUUID());} }② 启动 8001 自测检查是否通过 http://localhost:8001/pay/gateway/get/1 http://localhost:8001/pay/gateway/info 步骤 ① 9527 网关 YML 新增配置 server:   port: 9527spring:   application:     name: cloud-gateway #以微服务注册进consul或nacos服务列表内   cloud:     consul: #配置consul地址       host: localhost       port: 8500       discovery:         prefer-ip-address: true         service-name: ${spring.application.name}    gateway:       routes:         - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           uri: http://localhost:8001                #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/get/**              # 断言路径相匹配的进行路由         - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           uri: http://localhost:8001                #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/info/**              # 断言路径相匹配的进行路由 ② 启动 8001 和 9527 添加网关前http://localhost:8001/pay/gateway/get/1                       http://localhost:8001/pay/gateway/info 添加网关后http://localhost:9527/pay/gateway/get/1                       http://localhost:9527/pay/gateway/info 隐真示假映射说明 ​ 运行结果 ​ ​ 目前 8001 支付微服务前面添加 GateWay 成功GateWay9527 → Pay8001 ​ 2服务间调用添加网关 需求我们启动 80 订单微服务要求访问 9527 网关后才能访问 800180 → 9527 → 8001 ​ Question网关不是用于前端 web 请求转发到后端吗怎么用于微服务之间了我们不是有 openfeign 实现服务间接口调用了吗 没错微服务之间的确没必要使用网关但该前提是这些服务都是同一家公司的系统内环境。 设想如果淘宝调用顺丰的接口这是不是微服务之间的调用但这属于系统外访问应当先找网关在找真实服务。 我们现在模拟的就是后者你可以把订单 80 服务和支付 8001 服务理解成两个不同公司的服务。 同时这也很好的解释了我们一开始将 gateway 和 nginx 做对比说微服务之间需要做的事情就可以通过网关来实现更加容易快速上手。设想这里如果使用 nginx 来实现会不会就没这么简单了 步骤 ① 修改 PayFeignApi 接口添加方法 FeignClient(value cloud-payment-service) public interface PayFeignApi {...//GateWay进行网关测试案例01GetMapping(value /pay/gateway/get/{id})public ResultData getById(PathVariable(id) Integer id);//GateWay进行网关测试案例02GetMapping(value /pay/gateway/info)public ResultDataString getGatewayInfo(); } ② feign80 新建 OrderGateWayController 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 ResultDataString getGatewayInfo(){return payFeignApi.getGatewayInfo();} } ③ 测试启动 80、网关9527、8001 http://localhost/feign/pay/gateway/get/1 http://localhost/feign/pay/gateway/info  测试成功 但真的成功了吗我们关闭网关再测一次只启动 80 和 8001 http://localhost/feign/pay/gateway/get/1 http://localhost/feign/pay/gateway/info  我们发现开不开网关的效果都一样openfeign 直接绕过了网关。 这是为什么呢  还是刚才说的同一家公司系统内环境微服务之间无需网关直接通过 openfeign 调用。 但不同家公司系统外访问需要先找网关在找真实服务。 我们真的将 80 和 8001 分隔开了吗 在 PayFeignApi 中我们 feign 接口中的服务名还是 8001能够直接访问。 如果真的要将 80 和 8001 分隔开我们这时候是不是应该是 gateway网关的微服务名让 80 直接通过 feign 先去找网关 此时打开 80、网关9527、8001进行测试 打开 80、8001关闭网关9527进行测试 当没有网关的时候发生 503 异常无法访问到 8001。 至此才是真正测试成功 3存在问题 在网关9527 的 yml 配置中我们将映射地址和端口号写死 后续如果发生改变只能一个个修改这是非常不利的 6.Gateway高级特性 1Route路由 因为 openfeign 天然支持负载均衡lbLoadBalancer所以我们可以用 lb://微服务名来动态获取服务 uri解决映射写死问题 但如果不支持负载均衡lb就只能手动指定服务的实际 URL。 修改 9527网关的 yml server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/info/** # 断言路径相匹配的进行路由 此时如果 8001 的地址和端口号发生改变也不会影响到 9527网关的配置它仍然可以根据服务名动态获取服务 URI。 2Predicate断言谓词 Ⅰ. 介绍 官网Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/4.0.4/reference/html/#gateway-request-predicates-factories Route Predicate Factories 这个到底是什么   Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础架构的一部分。 Spring Cloud Gateway 包括许多内置的 RoutePredicateFactory路由谓词工厂。所有这些 Predicate 都与 HTTP 请求的不同属性匹配。多个 RoutePredicateFactory 可以进行组合并通过逻辑 and。  启动微服务 gateway9527,看看 IDEA 后台的输出 可以看出gateway 一开始会加载默认自带的 RoutePredicateFactory。 整体架构  Ⅱ . 配置方法 两种配置方法二选一常用 shortcut 方式 ① Shortcut Configuration ② Fully Expanded Arguments Ⅲ . 常用的内置 Route Predicate 以下断言 api我们均采用 shortcut 方式配置 ① After Route Predicate 作用设置在某个时刻之后才可以访问应用场景到点秒杀 时间格式依赖于 ZonedDateTime 类其使用方法可以看下方 Java时间类--JDK8_jdk8时间类-CSDN博客https://blog.csdn.net/xpy2428507302/article/details/139217068?spm1001.2014.3001.5501 获取当前时间 public static void main(String[] args){ZonedDateTime now ZonedDateTime.now(); // 默认时区System.out.println(now); }配置 yml spring:   cloud:     gateway:       routes:         - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           #uri: http://localhost:8001                #匹配后提供服务的路由地址           uri: lb://cloud-payment-service          #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/get/**              # 断言路径相匹配的进行路由             - After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai] 如果时间没到就会显示当前时间状态码 404  时间到了之后就可以正常访问 ② Before Route Predicate  作用设置在某个时刻之前才可以访问 spring:   application:     name: cloud-gateway #以微服务注册进consul或nacos服务列表内   cloud:     consul: #配置consul地址       host: localhost       port: 8500       discovery:         prefer-ip-address: true         service-name: ${spring.application.name}     gateway:       routes:         - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           #uri: http://localhost:8001                #匹配后提供服务的路由地址           uri: lb://cloud-payment-service          #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/get/**              # 断言路径相匹配的进行路由             #- After2023-11-20T17:38:13.58691880008:00[Asia/Shanghai]            - Before2023-11-27T15:25:06.42456630008:00[Asia/Shanghai] #超过规定时间不可访问 ③ Between Route Predicate  作用设置在某个时间段之内才可以访问 spring:   application:     name: cloud-gateway #以微服务注册进consul或nacos服务列表内   cloud:     consul: #配置consul地址       host: localhost       port: 8500       discovery:         prefer-ip-address: true         service-name: ${spring.application.name}     gateway:       routes:         - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           #uri: http://localhost:8001                #匹配后提供服务的路由地址           uri: lb://cloud-payment-service          #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/get/**              # 断言路径相匹配的进行路由             #- After2023-11-20T17:38:13.58691880008:00[Asia/Shanghai]             #- Before2023-11-20T17:58:13.58691880008:00[Asia/Shanghai]             - Between2023-11-21T17:38:13.58691880008:00[Asia/Shanghai],2023-11-22T17:38:13.58691880008:00[Asia/Shanghai] ④ Cookie Route Predicate  Cookie Route Predicate需要两个参数一个是 Cookie name一个是正则表达式。 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]- Cookieusername,tom作用路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配。如果匹配上就会访问路由如果没有匹配上则不访问。 测试方法1: curl 原生命令 不带 cookie 参数curl http://localhost:9527/pay/gateway/get/1 cookie 参数校验成功curl http://localhost:9527/pay/gateway/get/1 --cookie usernametom 测试方法2postman 测试方法3chrome浏览器  直接打开网址会显示 404此时 F12 打开开发者模式 设置 cookie再次刷新页面访问成功 ⑤ Header Route Predicate 两个参数一个是属性名称和一个正则表达式这个属性值和正则表达式匹配则执行。  spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式 有关正则表达式的用法可以看下方 java正则表达式_java 正则表达式-CSDN博客https://blog.csdn.net/xpy2428507302/article/details/139185880?spm1001.2014.3001.5501测试方法1:原生命令 错误curl http://localhost:9527/pay/gateway/get/1 错误curl http://localhost:9527/pay/gateway/get/1 -H X-Request-Id:abcd 正确curl http://localhost:9527/pay/gateway/get/1 -H X-Request-Id:123456 测试方法2postman ⑥ Host Route Predicate  Host Route Predicate 接收一个参数一组匹配的主机名模板列表该模板是 Ant 样式的模板用 . 号作为分隔符。 它通过参数中的主机地址作为匹配规则。 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom#- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式- Host**.baidu.com测试方法1原生命令正确 curl http://localhost:9527/pay/gateway/get/1 -H Host:www.baidu.com 正确 curl http://localhost:9527/pay/gateway/get/1 -H Host:java.baidu.com 错误 curl http://localhost:9527/pay/gateway/get/1 -H Host:java.baidu.net 测试方法2postman  ⑦ Path Route Predicate 作用路径相匹配的进行路由  spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/info/** # 断言路径相匹配的进行路由⑧ Query Route Predicate 支持传入两个参数一个是属性名一个为正则表达式可以是属性名。  spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom#- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host**.baidu.com- Queryusername, \d # 要有参数名username并且值还要是整数才能路由测试 正确http://localhost:9527/pay/gateway/get/1?username123 错误http://localhost:9527/pay/gateway/get/1?usernameabc ⑨ RemoteAddr route predicate 作用 请求的远程地址与设置的源相匹配的允许访问路由 Question什么是 CIPR 网路 IP 划分  举例192.168.31.1/24 表示 IP 地址是192.168.31.1 24 表示网络号为前 24 位即子网掩码为255.255.255.0000 0000即 255.255.255.0 则主机号有 32 − 24 8 位允许在同一网络中最多有 2^8 256 个地址从 192.168.31.0 到 192.168.31.255其中 192.168.31.0 是网络地址192.168.31.255 是广播地址所以实际可用的主机地址为 192.168.31.1 ~ 192.168.31.254。 cmd 输入ipconfig查看自己的 ip 地址 我的子网掩码是 255.255.255.0所以和上面例子一样前 24 位为网络号。 IP地址: 00001010.11000111.10110100.11001100 子网掩码: 11111111.11111111.11111111.00000000 ------------------------------------------------ 子网地址: 00001010.11000111.10110100.00000000 将 ip 地址和子网掩码进行与操作得到所属网络 IP 为 10.199.180.0/24实际可用的主机地址为 10.199.100.1 ~ 10.199.100.254。 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom#- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host**.baidu.com#- Queryusername, \d # 要有参数名username并且值还要是整数才能路由- RemoteAddr10.199.180.0/24 # 外部访问我的IP限制最大跨度不超过32目前是1~24它们是 CIDR 表示法。(10.199.180.1 - 10.199.180.255)通过本地的 ip 地址进行远程访问  ⑩ Method Route Predicate  作用配置某个请求地址只能用 Get / Post 方法访问方法限制  总结 Predicate 就是为了实现一组匹配规则让请求过来找到对应的 Route 进行处理。 Ⅳ . 自定义断言 ① 前言 Question原有的断言配置不满足业务怎么办 此时我们就需要自定义断言如何自定义我们参考一下 AfterRoutePredicateFactory 的源码 总体架构 结论 ① 开头任意取名但是必须以 RoutePredicateFactory 后缀结尾  开头取的名字就是 application.yml 中 predicates 下作为判断的前缀比如 After ② 二选一 要么继承 AbstractRoutePredicateFactory 抽象类要么实现 RoutePredicateFactory 接口 ② 编写步骤 需求说明自定义配置会员等级userType按照钻/金/银和yml配置的会员等级进行匹配判断是否可以访问 i . 新建类名 XXX 需要以 RoutePredicateFactory 结尾并继承 AbstractRoutePredicateFactory 类 注意 Component 注解不能忘写必须要保证自定义的断言能被springioc 扫描到 ii .  重写 apply 方法 Overridepublic PredicateServerWebExchange apply(MyRoutePredicateFactory.Config config){return null;} iii . 新建 apply 方法所需要的静态内部类 MyRoutePredicateFactory.Config 这个 Config 类就是我们的路由断言规则非常重要 //这个 Config 类就是我们的路由断言规则非常重要Validatedpublic static class Config{SetterGetterNotEmptyprivate String userType; //钻、金、银等用户等级} iv . 空参构造方法内部调用 super public MyRoutePredicateFactory(){super(MyRoutePredicateFactory.Config.class);} v . 重写apply方法第二版 Overridepublic PredicateServerWebExchange apply(Config config){return new PredicateServerWebExchange(){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;}};} 完整代码 //需求说明自定义配置会员等级userType按照钻/金/银和yml配置的会员等级进行匹配判断是否可以访问 Component public class MyRoutePredicateFactory extends AbstractRoutePredicateFactoryMyRoutePredicateFactory.Config {public MyRoutePredicateFactory(){super(Config.class);}Overridepublic PredicateServerWebExchange apply(Config config){return new PredicateServerWebExchange(){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;}};}//这个 Config 类就是我们的路由断言规则非常重要Validatedpublic static class Config{SetterGetterNotEmptyprivate String userType; //钻、金、银等用户等级} } ③ 测试 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom#- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host**.baidu.com#- Queryusername, \d # 要有参数名username并且值还要是整数才能路由#- RemoteAddr10.199.180.0/24 # 外部访问我的IP限制最大跨度不超过32目前是1~24它们是 CIDR 表示法。(10.199.180.1 - 10.199.180.255)- Mydiamond # 表示必须是钻石会员 启动 9527我们发现控制台报错 刚才使用的是 shortcut 方式进行的配置 不妨我们使用 Fully Expanded Arguments 方式进行配置试试 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/get/** # 断言路径相匹配的进行路由#- After2024-11-18T22:50:13.58691880008:00[Asia/Shanghai]#- Cookieusername,tom#- HeaderX-Request-Id, \d # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host**.baidu.com#- Queryusername, \d # 要有参数名username并且值还要是整数才能路由#- RemoteAddr10.199.180.0/24 # 外部访问我的IP限制最大跨度不超过32目前是1~24它们是 CIDR 表示法。(10.199.180.1 - 10.199.180.255)#- Mydiamond # 表示必须是钻石会员- name: Myargs:userType: diamond 此时重启 9527再次进行测试 此时控制台没有发生报错我们打开浏览器进行测试 正确http://localhost:9527/pay/gateway/get/1?userTypediamond 错误http://localhost:9527/pay/gateway/get/1?userTypegold 测试成功 Question那么为什么 shortcut 方式配置会无法失败而 Fully Expanded Arguments 方式配置就可以成功运行呢 我们再次打开 AfterRoutePredicateFactory 的源码我们发现存在一个 shortcutFieldOrder 方法。 从名字就可以看出该方法名和 shortcut 方式有关但我们并未实现  原因缺少 shortcutFieldOrder 方法的实现所以不支持短格式  所以我们也需要在自定义的断言类中重写该方法  Overridepublic ListString shortcutFieldOrder() {return Collections.singletonList(userType);} 此时我们再使用 shortcut 方式配置重启 9527就可以成功运行了 3 Filter过滤 Ⅰ. 介绍 类似于 SpringMVC 里面的的拦截器 InterceptorServlet 的过滤器。 “pre” 和 “post” 分别会在请求被执行前调用和被执行后调用用来修改请求和响应信息 作用 请求鉴权异常处理记录接口调用时长统计重点大厂面试设计题 类型 i . 全局默认过滤器 Global Filters gateway 出厂默认已有的直接用即可主要作用于所有的路由不需要在配置文件中配置作用在所有的路由上实现 GlobalFilter 接口即可ii . 单一内置过滤器 GatewayFilter 也可以称为网关过滤器这种过滤器主要是作用于单一路由或者某个路由分组iii . 自定义过滤器 Ⅱ . Gateway内置的过滤器 这里只讲解常见的和通用的分成 5 个相关组进行讲解 ① 请求头RequestHeader相关组 i . The AddRequestHeader GatewayFilter Factory 作用手动往请求头中添加 kv 键值对 步骤 1.在 8001 的 PayGateWayController 新增方法 RestController public class PayGateWayController {...GetMapping(value /pay/gateway/filter)public ResultDataString getGatewayFilter(HttpServletRequest request){String result ;EnumerationString 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-name1)|| headName.equalsIgnoreCase(X-Request-name2)) {result resultheadName \t headValue ;}}return ResultData.success(getGatewayFilter 过滤器 test result \t DateUtil.now());} } 细节 这里的 X-Request-name1 和 X-Request-name2 在原本请求头中并没有是我后续在 yml 中手动添加的为了方便显示我做了一些处理。 2. 9527 网关 YML 添加过滤内容 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址filters:- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置- AddRequestHeaderX-Request-name2,jerry 3. 重启 9527 和 8001 访问地址http://localhost:9527/pay/gateway/filter 我们发现控制台打印请求头的结果中出现了我们手动添加的 X-Request-name1 和 X-Request-name2 反之如果 9527 的 yml 中没有手动配置控制台打印请求头的结果中也将没有  ii . The RemoveRequestHeader GatewayFilter Factory 作用 删除请求头中指定名字的 kv 键值对 我们现在要删除请求头中名为sec-fetch-site 的内容 删除 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址filters:- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置- AddRequestHeaderX-Request-name2,jerry - RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site 重启 9527 和 8001访问地址http://localhost:9527/pay/gateway/filter 发现控制台打印请求头中的结果中 sec-fetch-site 已被删除 iii . The SetRequestHeader GatewayFilter Factory 作用修改请求头中指定名字的值  我们现在要修改请求头中名为sec-fetch-mode 的内容修改为 Blue 修改 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址filters:- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置- AddRequestHeaderX-Request-name2,jerry- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue 重启 9527 和 8001访问地址http://localhost:9527/pay/gateway/filter  发现控制台打印请求头中的结果中sec-fetch-mode 的值已经被修改为 Blue ② 请求参数RequestParameter相关组 i . The AddRequestParameter GatewayFilter Factory ii . The RemoveRequestParameter GatewayFilter Factory 我们将上述两个一起测试 1.修改 8001 的 PayGateWayController RestController public class PayGateWayController {...GetMapping(value /pay/gateway/filter)public ResultDataString getGatewayFilter(HttpServletRequest request){String result ;EnumerationString 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-name1)|| headName.equalsIgnoreCase(X-Request-name2)) {result resultheadName \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());} } 2. 修改 9527 的 yml spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址filters:- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置- AddRequestHeaderX-Request-name2,jerry- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue- AddRequestParametercustomerId,9527001 # 新增请求参数Parameterk v- RemoveRequestParametercustomerName # 删除url请求参数customerName你传递过来也是null重启 9527 和 8001访问地址 http://localhost:9527/pay/gateway/filter http://localhost:9527/pay/gateway/filter?customerId9999customerNamez3 我们发现 如果没有传 customerId那就是我们设置的默认值9527001如果传了就会覆盖默认值。 不管有没有传 customerName它都会被删除取到的值为 null ③ 回应头ResponseHeader相关组 i . The AddResponseHeader GatewayFilter Factory ii . The SetResponseHeader GatewayFilter Factory iii . The RemoveResponseHeader GatewayFilter Factory 我们将上述两个一起测试 修改前的响应头 修改  spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址filters:- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置- AddRequestHeaderX-Request-name2,jerry- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue- AddRequestParametercustomerId,9527001 # 新增请求参数Parameterk,v- RemoveRequestParametercustomerName # 删除url请求参数customerName你传递过来也是null- AddResponseHeaderX-Response-Color, BlueResponse # 新增响应参数X-Response-Color并设值为BlueResponse- SetResponseHeaderDate,2099-11-11 # 设置回应头Date值为2099-11-11- RemoveResponseHeaderContent-Type # 将默认自带Content-Type回应属性删除 重启 9527 和 8001访问地址http://localhost:9527/pay/gateway/filter ④ 前缀和路径相关组 i . The PrefixPath GatewayFilter Factory 作用自动添加路径前缀 之前的正确地址http://localhost:9527/pay/gateway/filter 修改后 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- id: pay_routh3 #pay_routh3uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:#- Path/pay/gateway/filter/** # 断言路径相匹配的进行路由 默认正确地址- Path/gateway/filter/** # 断言为配合PrefixPath测试过滤暂时注释掉/payfilters:- PrefixPath/pay # 添加路由前缀/pay#- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置#- AddRequestHeaderX-Request-name2,jerry#- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site#- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue#- AddRequestParametercustomerId,9527001 # 新增请求参数Parameterk,v#- RemoveRequestParametercustomerName # 删除url请求参数customerName你传递过来也是null#- AddResponseHeaderX-Response-Color, BlueResponse # 新增请求参数X-Response-Color并设值为BlueResponse#- SetResponseHeaderDate,2099-11-11 # 设置回应头Date值为2099-11-11#- RemoveResponseHeaderContent-Type # 将默认自带Content-Type回应属性删除 拆分说明 之前完整正确地址 http://localhost:9527/pay/gateway/filter 现在完整组合地址 PrefixPath Path 实际调用地址 http://localhost:9527/gateway/filter 相当于说前缀被过滤器统一管理了。 测试重启 9527 和 8001访问地址http://localhost:9527/gateway/filter ii . The SetPath GatewayFilter Factory 作用访问路径修改 之前的正确地址http://localhost:9527/pay/gateway/filter 修改后 server:port: 9527spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- 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:- SetPath/pay/gateway/{segment} # {segment}表示占位符你写abc也行但要上下一致#- PrefixPath/pay # 添加路由前缀/pay#- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置#- AddRequestHeaderX-Request-name2,jerry#- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site#- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue#- AddRequestParametercustomerId,9527001 # 新增请求参数Parameterk v#- RemoveRequestParametercustomerName # 删除url请求参数customerName你传递过来也是null#- AddResponseHeaderX-Response-Color, BlueResponse # 新增请求参数X-Response-Color并设值为BlueResponse#- SetResponseHeaderDate,2099-11-11 # 设置回应头Date值为2099-11-11#- RemoveResponseHeaderContent-Type # 将默认自带Content-Type回应属性删除替换说明 /XYZ/abc/{segment}{segment} 就是个占位符等价于 SetPath 后面指定的 {segment} 内容 浏览器访问地址: http://localhost:9527/XYZ/abc/filter 实际微服务地址http://localhost:9527/pay/gateway/filter 测试重启 9527 和 8001访问地址http://localhost:9527/XYZ/abc/filter iii . The RedirectTo GatewayFilter Factory 作用重定向到某个页面  spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- 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:- RedirectTo302, http://www.baidu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.baidu.com/#- SetPath/pay/gateway/{segment} # {segment}表示占位符你写abc也行但要上下一致#- PrefixPath/pay # 添加路由前缀/pay#- AddRequestHeaderX-Request-name1,tom # 请求头kv若一头含有多参则重写一行设置#- AddRequestHeaderX-Request-name2,jerry#- RemoveRequestHeadersec-fetch-site # 删除请求头sec-fetch-site#- SetRequestHeadersec-fetch-mode, Blue # 将请求头sec-fetch-mode对应的值修改为Blue#- AddRequestParametercustomerId,9527001 # 新增请求参数Parameterk v#- RemoveRequestParametercustomerName # 删除url请求参数customerName你传递过来也是null#- AddResponseHeaderX-Response-Color, BlueResponse # 新增请求参数X-Response-Color并设值为BlueResponse#- SetResponseHeaderDate,2099-11-11 # 设置回应头Date值为2099-11-11#- RemoveResponseHeaderContent-Type # 将默认自带Content-Type回应属性删除 重启 9527 和 8001访问地址http://localhost:9527/pay/gateway/filter将直接被重定向到百度首页。 ⑤ 其他Default Filters 配置在此处相当于全局通用自定义秒变 Global但作用范围只在网关中定义的所有路由。 因为 Global Filters 在代码中定义全局作用于所有请求无论是否匹配路由。 Ⅲ . Gateway 自定义过滤器  ① 自定义全局过滤器 需求统计接口调用耗时情况面试题重点 解决办法自定义接口调用耗时统计的全局过滤器  步骤 1. 新建类 MyGlobalFilter 并实现 GlobalFilterOrdered 两个接口 Component Slf4j public class MyGlobalFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain){return null;}Overridepublic int getOrder(){return 0;} }细节 i . MyGlobalFilter 实现了两个接口GlobalFilter 和 Ordered  GlobalFilterSpring Cloud Gateway 的接口用于定义过滤器的行为。Ordered用来定义过滤器的执行顺序。getOrder() 方法返回值越小优先级越高。 ii . filter 方法是过滤器的核心逻辑接收 ServerWebExchange 和 GatewayFilterChain 两个参数 ServerWebExchange exchange: 包含 HTTP 请求和响应信息。GatewayFilterChain chain: 用于链式调用下一个过滤器。 2. 实现 MyGlobalFilter 类的内部逻辑 Component Slf4j public class MyGlobalFilter implements GlobalFilter, Ordered {private static final String BEGIN_VISIT_TIME begin_visit_time;//开始访问时间Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain){//先记录下访问接口的开始时间exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());//then是回调方法当请求处理完成响应回来才执行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) 毫秒);log.info(###################################################);System.out.println();}}));}Overridepublic int getOrder(){return 0;} } 细节 i . then 是一个 Mono 的操作符它表示在前一个异步任务完成之后执行新的任务。在本例中新的任务是一个 Runnable用于记录日志和计算请求时间。 ii . Mono.fromRunnable(...) 接收一个 Runnable 接口实现这个接口只有一个 run() 方法表示要执行的任务。 3. yml为了方便测试我们注释掉之前配置的断言和过滤器 spring:   application:     name: cloud-gateway #以微服务注册进consul或nacos服务列表内   cloud:     consul: #配置consul地址       host: localhost       port: 8500       discovery:         prefer-ip-address: true         service-name: ${spring.application.name}     gateway:       routes:         - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           uri: lb://cloud-payment-service                #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/get/**              # 断言路径相匹配的进行路由        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID)没有固定规则但要求唯一建议配合服务名           uri: lb://cloud-payment-service           predicates:             - Path/pay/gateway/info/**              # 断言路径相匹配的进行路由        - id: pay_routh3 #pay_routh3           uri: lb://cloud-payment-service                #匹配后提供服务的路由地址           predicates:             - Path/pay/gateway/filter/**              # 断言路径相匹配的进行路由默认正确地址 4. 测试重启 9527 和 8001访问 http://localhost:9527/pay/gateway/info http://localhost:9527/pay/gateway/get/1 http://localhost:9527/pay/gateway/filter 解释 通过这种方法不仅可以将业务代码和需求完全隔离开而且还不用像 spring AOP 一样需要添加注解。 如果新增一个业务只要 yml 中添加了该路由什么都不用做就自动实现该功能 ② 自定义局部条件过滤器 同理和自定义断言一样我们参考一下 AddResponseHeaderGatewayFilterFactory 的源码 我们发现和断言几乎一致 结论 ① 开头任意取名但是必须以 GatewayFilterFactory 后缀结尾  开头取的名字就是 application.yml 中 filters 下作为判断的前缀比如 AddResponseHeader) ② 二选一 要么继承 AbstractGatewayFilterFactory 抽象类要么实现 GatewayFilterFactory 接口 步骤 i . 新建类名 XXX 需要以 GatewayFilterFactory 结尾并继承 AbstractGatewayFilterFactory 类 注意 Component 注解不能忘写必须要保证自定义的过滤器能被springioc 扫描到  ii .  重写 apply 方法 Overridepublic GatewayFilter apply(MyGatewayFilterFactory.Config config){return null;} iii . 新建 apply 方法所需要的静态内部类 MyGatewayFilterFactory.Config 这个 Config 类就是我们的路由过滤规则非常重要 public static class Config {SetterGetterprivate String param;//设定一个参数该参数的值必须作为key传递才能访问} 需求请求发送时必须携带一个 keykey 的名字就是 param 的值。 比如param 的值为 name发送请求时必须携带 namexxx iv . 空参构造方法内部调用 super public MyGatewayFilterFactory() {super(MyGatewayFilterFactory.Config.class);} v . 重写 apply 方法第二版 Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request exchange.getRequest();//请求中带有key名字为param的值进入逻辑if (request.getQueryParams().containsKey(config.getParam())) {//打印request.getQueryParams().get(config.getParam()).forEach((value) - {System.out.println(获取到的key为 config.param);System.out.println(获取到的value为 value);});//放行return chain.filter(exchange);} else {//设置异常状态码exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);return exchange.getResponse().setComplete();}}};} Ⅵ . 重写 shortcutFieldOrder 方法 Overridepublic ListString shortcutFieldOrder() {return Arrays.asList(param);} 完整代码 Component public class MyGatewayFilterFactory extends AbstractGatewayFilterFactoryMyGatewayFilterFactory.Config {public MyGatewayFilterFactory() {super(Config.class);}Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request exchange.getRequest();//请求中带有key名字为param的值进入逻辑if (request.getQueryParams().containsKey(config.getParam())) {//打印request.getQueryParams().get(config.getParam()).forEach((value) - {System.out.println(获取到的key为 config.param);System.out.println(获取到的value为 value);});//放行return chain.filter(exchange);} else {//设置异常状态码exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);return exchange.getResponse().setComplete();}}};}Overridepublic ListString shortcutFieldOrder() {return Arrays.asList(param);}public static class Config {SetterGetterprivate String param;//设定一个参数该参数的值必须作为key传递才能访问} } Ⅶ . yml 文件配置 spring:application:name: cloud-gateway #以微服务注册进consul或nacos服务列表内cloud:consul: #配置consul地址host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}gateway:routes:- 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:- Myname # 表示param的值为name发送请求时必须传递name Ⅷ . 测试重启 9527 和 8001访问地址 错误http://localhost:9527/pay/gateway/filter 错误http://localhost:9527/pay/gateway/filter?abcjava 正确http://localhost:9527/pay/gateway/filter?namejava
http://www.hkea.cn/news/14382111/

相关文章:

  • 网站开发是什中国楼市最新消息
  • 怎样制作免费网站品牌网站方案
  • 康定网站建设公司模板支撑体系搭设规范
  • 天天做网站百度外推代发排名
  • 网站的会员功能佛山新网站建设机构
  • 高端网站建设 恩愉科技wordpress自动锚文本
  • 贵金属网站源码网站免费广告
  • 虚拟网站官网学做网站论坛vip视频
  • 建购物的网站需要多少钱四川seo策略
  • 做网站的表情包广州越秀网站建设公司
  • 邢台做网站推广服务小米的网站是哪个公司做的
  • 网站推广是什么玉树营销网站建设服务
  • 有什么做兼职的网站比较好网页字体导入wordpress
  • 网站seo顾问医疗营销的网站怎么做
  • 专用于做网站公司直播app制作公司
  • 先做网站后备案吗珠海响应式网站建设推广公司
  • 单位网站改版哪个网站查食品建设好
  • 宜昌网站开发四川网站排名
  • 财经网站源码 织梦网站源码什么意思
  • 秦皇岛网站搜索优化中国万网域名登录
  • 东莞网站优化哪个公司好国内的有什么好wordpress主题
  • 商城网站开发背景南通网络公司网站
  • 网站开发岗位说明书管理系统软件有哪些
  • 求职网站开发开题报告写作网站大全
  • cms管理手机网站企业网络推广网站建设
  • 做外贸需要做个英文网站吗南阳做网站哪个好
  • 做有支付系统的网站一般需要多少钱河南城市建设网站
  • 企业为什么要建站台呢wordpress数据输出
  • 做数据结构基础的网站衡水做wap网站
  • 建站公司哪家好 知道万维科技网站图片做伪静态