Spring Cloud Gateway 网关路由

一、路由断言

  • 路由断言就是判断路由转发的规则

二、路由过滤器

1. 路由过滤器可以实现对网关请求的处理,可以使用 Gateway 提供的,也可以自定义过滤器

2. 路由过滤器 GatewayFilter(默认不生效,只有配置到路由后才会生效):

  • 只对一个路由生效,配置到 routes 下,和 predicates 同级

  • 对所有路由生效:配置到 default-filters

3. 全局过滤器 GlobalFilter(所有路由都生效):声明后自动生效

三、网关请求处理流程

业务实战:如果要进行用户校验,应该在网关请求转发之前先完成对用户的校验,判断用户是否有请求权限

  • 网关请求转发:NettyRoutingFilter 的 PRE 阶段

做法:

1. 在 NettyRoutingFilter 之前的过滤器链中自定义过滤器完成登录校验

2. 在自定义过滤器 PRE 阶段完成登录校验(POST 阶段请求已经转发了,不符合业务:先登录才能请求)

3. 网关中没有业务逻辑,只是做路由转发,网关进行登录校验之后获取用户信息并没有实际作用(除了校验)

4. 网关将请求转发到微服务,微服务需要用户信息!网关需要将用户信息传给微服务

5. 怎么传?:网关将请求转发到微服务,其实就是发起了一次 HTTP 请求,可以将用户信息保存到请求头,微服务从请求头中取出用户信息,且不会对业务造成影响 ✔

6. 微服务之间的调用怎么获取用户信息?:网关只将用户信息传递给了一个微服务(cart-service),但是微服务之间会相互调用(trade-service 调用 cart-service)trade-service 并没有用户信息,cart-service 也不会自动将用户信息传递给调用它的微服务

  • 可以使用将用户信息保存到请求头的方式在微服务之间传递用户信息吗
  • 微服务之间的请求(OpenFeign)和网关与微服务之间(Spring Cloud Gateway 内置的)的请求不同,实现方式有差别

 

四、网关统一实现用户登录校验(基于 JWT)

1. 自定义过滤器并控制过滤器的顺序

  • 路由过滤器GatewayFilter(默认不生效,只有配置到路由后才会生效):

    • 只对一个路由生效,配置到 routes 下,和 predicates 同级

    • 对所有路由生效:配置到 default-filters

  •  全局过滤器 GlobalFilter(所有路由都生效):声明后自动生效

filter 方法解读:

  • 参数 1 ServerWebExchange exchange:网关内部的上下文对象,保存网关内部整个过滤器链的共享数据,如 request、response、session 及 一些自定义的共享属性,所有过滤器都可以从 exchange 中读取 / 存储共享数据

  • 参数 2 GatewayFilterChain chain:过滤器链,当前过滤器执行完之后,通过 chain 调用过滤器链中的下一个过滤器

网关采用的是非阻塞式的编程,利用 Mono 定义回调函数,等之后请求转发回来的返回结果有了再调用回调函数(过滤器中 POST 部分的逻辑),一般不用写回调

e.g 实际开发中遇到的回调:接口调用成功后统计接口调用次数 + 1,就是要等到返回结果是 ok 的再去执行调用次数 + 1 的逻辑!

  • 返回值 Mono<Void>:每个过滤器执行完之后直接返回 Mono

自定义过滤器的优先级比 NettyRoutingFilter 高即可,NettyRoutingFilter 的 order 值是 maxInt,优先级最低

// 1. 实现 GlobalFilter 接口中的 filter 方法
// 2. 实现 Orderd 接口的 getOrder 方法,通过 ORDER 控制过滤器优先级
// 3. 放行(将 exchange 传到下一个过滤器)

2. 在网关实现登录校验

  • 获取请求头

  • 判断请求路径是否需要拦截(有些路径不需要登录也可以查看)

    使用 Spring 提供的 AntPathMatcher 的 match() 方法来校验路径是否匹配指定的路径模式 pathPattern(/search/** 等路径)

private final AntPathMatcher antPathMatcher = newAntPathMatcher();

  • 获取 token

  • 校验并解析 token

  • 拦截未登录用户

    • 设置响应状态码:未登录 401

    • 终止流程

3. 网关传递用户信息给下游微服务

  • 传递

    • 使用上下文对象中修改请求的 API:mutate()

    • 将构造好的新的上下文对象传给下一个过滤器

  • 获取:微服务中的很多业务都需要获取用户信息,将从请求头中获取用户信息的逻辑写到拦截器中,统一获取;可能会有很多个微服务,写拦截器要在所有微服务里都写一遍?=> 写到公共模块 common 其他微服务都引入这个模块(依赖),就都有了拦截器的功能 ✔
    • 定义拦截器

      • 实现 HandlerInterceptor 接口其中的 preHandle() 方法,在 Controller 之前执行

      • 实现 afterCompletion() 方法在 Controller 执行完之后执行,清楚 ThreadLocal 中的用户信息

    • 注册拦截器:定义 SpringMVC 的配置类,实现 WebMvcConfigurer 中的 addInterceptors()

    • 扫描包:common 模块和微服务模块所在包不同,Spring 不会自动扫描到配置类,需要自己配置,实现 Spring 自动装配

    • 保存到 ThreadLocal 中,其他业务从 ThreadLocal 取出用户信息

注意❗网关模块不能使用 / 引用 SpringMVC 相关的类,Spring Cloud Gateway 的底层用的不是 SpringMVC,而是响应式的 webflux

网关项目也引入了 common 模块,但是 common 模块中定义了 SpringMVC 的拦截器,微服务项目需要该拦截器,网关不需要该拦截器,如何次拦截器配置类在有些情况(微服务模块)生效,有些情况(网关)不生效?

解决方法:让 SpringMVC 的配置类根据条件来加载,即判断是否有 SpringMVC(网关和其他微服务项目的差别就是是否有 SpringMVC,可以根据是否有 SpringMVC 中的核心 API DispatcherServlet)

实现:使用 Spring 的条件注解 @ConditionalOnClass(DispatcherServlet.class)

4.  微服务之间的信息传递(OpenFeign 传递用户)

用户信息是从 ThreadLocal 中取的,要先从请求头中获取用户信息才能存到 ThreadLocal 中,而请求头中的用户信息是网关向微服务发起请求时添加的,但是微服务之间的是直接调用的,没有经过网关,而是通过 OpenFeign 的远程调用,如何修改 OpenFeign 发起的请求?

  • OpenFeign 中提供了一个拦截器接口 RequestInterceptor,所有由 OpenFeign 发起的请求(远程调用)都会先调用拦截器处理请求

  • 其中的 RequestTemplate 类中提供了一些方法(如 header())可以让我们修改请求头

五、总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人机飞行原理,多旋翼无人机飞行原理详解

多旋翼无人机升空飞行的首要条件是动力&#xff0c;有了动力才能驱动旋粪旋转&#xff0c;才能产生克服重力所必需的升力。使旋翼产生升力&#xff0c;进而推动多旋翼无人机升空飞行的一套设备装置称为动力装置&#xff0c;包括多旋翼无人机的发动机以及保证发动机正常工作所必…

LibreOffice Calc 取消首字母自动大写 (Capitalize first letter of every sentence)

LibreOffice Calc 取消首字母自动大写 [Capitalize first letter of every sentence] 1. Tools -> AutoCorrect Options2. AutoCorrect -> Options -> Capitalize first letter of every sentenceReferences 1. Tools -> AutoCorrect Options 2. AutoCorrect ->…

论文介绍 One-step Diffusion 只需单步扩散生成!

论文介绍 One-step Diffusion with Distribution Matching Distillation 关注微信公众号: DeepGo 源码地址&#xff1a; https://tianweiy.github.io/dmd/ 论文地址&#xff1a; https://arxiv.org/abs/2311.18828 这篇论文介绍了一种新的图像生成方法&#xff0c;名为分布匹配…

C++三剑客之std::optional(一) : 使用详解

相关文章系列 C三剑客之std::optional(一) : 使用详解 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)&#xff1a;深入剖析 目录 1.概述 2.构建方式 2.1.默认构造 2.2.移动构造 2.3.拷贝构…

前端vue 数字 字符串 丢失精度问题

1.问题 后端返回的数据 是这样的 一个字符串类型的数据 前端要想显示这个 肯定需要使用Json.parse() 转换一下 但是 目前有一个问题 转换的确可以 showId:1206381711026823172 有一个这样的字段 转换了以后 发现 字段成了1206381711026823200 精度直接丢了 原本的数据…

假期作业 8

1、若有以下说明语句&#xff1a;int a[12]{1,2,3,4,5,6,7,8,9,10,11,12};char c’a’,d,g;则数值为4的表达式是&#xff08; B&#xff09;。 A&#xff09;a[g-c] B&#xff09;a[4] C&#xff09;a[‘d’-‘c’] D&#xff09;a[‘d’-c] 2、假…

【C++ 02】类和对象 1:初识类和对象

文章目录 &#x1f308; Ⅰ 面向对象介绍&#x1f308; Ⅱ 类的引入&#x1f308; Ⅲ 类的定义格式1. 声明和定义不分离2. 声明和定义分离 &#x1f308; Ⅳ 类的访问限定符&#x1f308; Ⅴ 类的作用域&#x1f308; Ⅵ 类的实例化&#x1f308; Ⅶ this 指针 &#x1f308; Ⅰ…

【Java程序设计】【C00254】基于Springboot的java学习平台(有论文)

基于Springboot的java学习平台&#xff08;有论文&#xff09;&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的学习平台 本系统分为系统功能模块、管理员功能模块、教师功能模块以及学生功能模块。 系统功能模块&#xff1a;在平台…

LLM大模型常见问题解答(3)

简要描述下列概念在大语言模型中的作用 Transformer 架构Attention 机制预训练与微调过拟合和欠拟合 Transformer 架构 Transformer是一种基于自注意力机制的深度学习模型&#xff0c;它在论文“Attention Is All You Need”中首次提出。与此前流行的循环神经网络&#xff0…

第四节 zookeeper集群与分布式锁

目录 1. Zookeeper集群操作 1.1 客户端操作zk集群 1.2 模拟集群异常操作 1.3 curate客户端连接zookeeper集群 2. Zookeeper实战案例 2.1 创建项目引入依赖 2.2 获取zk客户端对象 2.3 常用API 2.4 客户端向服务端写入数据流程 2.5 服务器动态上下线、客户端动态监听 2…

力扣题目训练(8)

2024年2月1日力扣题目训练 2024年2月1日力扣题目训练404. 左叶子之和405. 数字转换为十六进制数409. 最长回文串116. 填充每个节点的下一个右侧节点指针120. 三角形最小路径和60. 排列序列 2024年2月1日力扣题目训练 2024年2月1日第八天编程训练&#xff0c;今天主要是进行一些…

AcWing 802. 区间和 离散化

文章目录 题目链接题目描述解题思路代码实现总结 题目链接 链接: AcWing 802. 区间和 题目描述 解题思路 离散化是一种常用的技巧&#xff0c;它能够将原始的连续数值转换为一组离散的值&#xff0c;从而简化问题的处理。在这段代码中&#xff0c;离散化的过程主要分为三个步…

探索Nginx:强大的开源Web服务器与反向代理

一、引言 随着互联网的飞速发展&#xff0c;Web服务器在现代技术架构中扮演着至关重要的角色。Nginx&#xff08;发音为“engine x”&#xff09;是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。Nginx因其卓越的性能、稳定性和灵活性&…

02.数据结构

一、链表 作用&#xff1a;用于写邻接表&#xff1b; 邻接表作用&#xff1a;用于存储图或树&#xff1b; 1、用数组模拟单链表 #include<iostream> using namespace std;const int N 100010;// head 表示头结点的下标 // e[i] 表示结点i的值 // ne[i] 表示结点i的ne…

前端工程化面试题 | 08.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

DS Wannabe之5-AM Project: DS 30day int prep day14

Q1. What is Autoencoder? 自编码器是什么&#xff1f; 自编码器是一种特殊类型的神经网络&#xff0c;它通过无监督学习尝试复现其输入数据。它通常包含两部分&#xff1a;编码器和解码器。编码器压缩输入数据成为一个低维度的中间表示&#xff0c;解码器则从这个中间表示重…

CentOS 7.9安装Tesla M4驱动、CUDA和cuDNN

正文共&#xff1a;1333 字 21 图&#xff0c;预估阅读时间&#xff1a;2 分钟 上次我们在Windows上尝试用Tesla M4配置深度学习环境&#xff08;TensorFlow识别GPU难道就这么难吗&#xff1f;还是我的GPU有问题&#xff1f;&#xff09;&#xff0c;但是失败了。考虑到Windows…

BIO、NIO、Netty演化总结

关于BIO&#xff08;关于Java NIO的的思考-CSDN博客&#xff09;和NIO&#xff08;关于Java NIO的的思考-CSDN博客&#xff09;在之前的博客里面已经有详细的讲解&#xff0c;这里再总结一下最近学习netty源码的的心得体会 在之前的NIO博客中我们知道接受客户端连接和IO事件的…

Vulnhub靶机:hacksudo-ProximaCentauri

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;hacksudo-ProximaCentauri&#xff08;10.0.2.51&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhu…

算法学习——LeetCode力扣二叉树篇4

算法学习——LeetCode力扣二叉树篇4 222. 完全二叉树的节点个数 222. 完全二叉树的节点个数 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xf…