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())可以让我们修改请求头

五、总结

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

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

相关文章

浅谈进制的转换

本文创作灵感来自CSDN咸鱼WCY 的 咸鱼小白学嵌入式之C语言&#xff08;2.进制&#xff09; 博主更完就没更了&#xff0c;决定书接上回&#xff08;喜 进制是个啥 要理解进制&#xff0c;首先哈&#xff0c;咱得知道不同进制的含义 说到底&#xff0c;各个进制其实有点像在…

学生公寓|基于Springboot的学生公寓管理系统设计与实现(源码+数据库+文档)

学生公寓管理系统目录 目录 基于Springboot的学生公寓管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、宿舍列表 2、宿舍公告信息管理 3、宿舍公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八…

洛谷: [CSP-J2019] 公交换乘

题目描述 著名旅游城市 B 市为了鼓励大家采用公共交通方式出行&#xff0c;推出了一种地铁换乘公交车的优惠方案&#xff1a; 在搭乘一次地铁后可以获得一张优惠票&#xff0c;有效期为 45 分钟&#xff0c;在有效期内可以消耗这张优惠票&#xff0c;免费搭乘一次票价不超过地…

学生成绩管理系统|基于Springboot的学生成绩管理系统设计与实现(源码+数据库+文档)

学生成绩管理系统目录 目录 基于Springboot的学生成绩管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能模块 2、学生功能模块 3、教师功能模块 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源…

AI引领低代码革命:未来应用开发的新主流

距离ChatGPT发布已经过去快一年时间。 在这一年里&#xff0c;以ChatGPT为代表的自然语言处理领域的重大进步&#xff0c;为我们的对话系统和语言交流提供了更加智能和自然的体验。随着ChatGPT的应用不断扩大&#xff0c;人们开始认识到人工智能&#xff08;AI&#xff09;技术…

elasticsearch增删改查

一、数据类型 1、字符串类型 &#xff08;1&#xff09;text &#xff08;2&#xff09;keyword 2、数值类型 &#xff08;1&#xff09;long、integer、short、byte、float、double 3、日期类型 &#xff08;1&#xff09;date 4、布尔类型 &#xff08;1&#xff0…

【AI绘图】初见·小白入门stable diffusion的初体验

首先&#xff0c;感谢赛博菩萨秋葉aaaki的整合包 上手 stable diffusion还是挺好上手的&#xff08;如果使用整合包的话&#xff09;&#xff0c;看看界面功能介绍简单写几个prompt就能生成图片了。 尝试 我在网上找了一张赛博朋克边缘行者Lucy的cos图&#xff0c;可能会侵…

假期作业 2月8日

数据类型与作用域练习 1、选择题 1.1、以下选项中,不能作为合法常量的是 __________ A&#xff09;1.234e04 B&#xff09;1.234e0.4 C&#xff09;1.234e4 D&#xff09;1.234e0 1.2、以下定义变量并初始化错误的是_____________。 A) char c1 ‘H’ &#xff…

开发自定义标记应用程序

开发自定义标记应用程序 问题陈述 Larry Williams 是ABC Inc.公司的CEO,他希望公司能够拥有一个交互式网站以向访问网站的用户表示问候并显示当前时间。他还希望最终用户能够指定主页的背景颜色。您是公司的网站管理员。Larry要您修改网站的主页,以便向最终用户显示自定义问…

Linux篇:网络基础1

一、网络基础&#xff1a;网络本质就是在获取和传输数据&#xff0c;而系统的本质是在加工和处理数据。 1、应用问题&#xff1a; ①如何处理发来的数据&#xff1f;—https/http/ftp/smtp ②长距离传输的数据丢失的问题&#xff1f;——TCP协议 ③如何定位的主机的问题&#…

Redis集中管理Session和系统初始化参数详解

Redis 是一个开源的、基于内存的键值存储系统&#xff0c;通常用作数据库、缓存或消息传递系统。在 Web 应用程序中&#xff0c;Redis 常用于集中管理 Session 数据和系统初始化参数。 Redis 管理 Session Session 是 Web 应用程序中用于保持用户状态的一种机制…

鸿蒙小案例-你画我猜

鸿蒙小案例-你画我猜 1.准备组件(组件布局) 2.实现跟随鼠标画笔画出图案功能 3.实现复制上面的画笔的图案功能 4.其他小功能1.组件的准备 画布的组件官方给的API是Canvas&#xff0c;需要传递一个参数CanvasRenderingContext2D 直接搜索API 使用官方案例 private settings: …

L2-1 点赞狂魔——pta(题解)

微博上有个“点赞”功能&#xff0c;你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签&#xff0c;而你点赞的博文的类型&#xff0c;也间接刻画了你的特性。然而有这么一种人&#xff0c;他们会通过给自己看到的一切内容点赞来狂刷存在感&#xff0c;这…

【蓝桥杯Python】试题 算法训练 藏匿的刺客

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 强大的kAc建立了强大的帝国&#xff0c;但人民深受其学霸及23文化的压迫&#xff0c;于是勇敢的鹏决心反抗。   kAc帝国防守…

C语言——求 1+12+123+……前 n 项之和,其中n 是从键盘输入的一个数字(1~9)。

一、问题 求 112123……前 n 项之和&#xff0c;其中n 是从键盘输入的一个数字&#xff08;1~9&#xff09; 二、解答 #include <stdio.h>int main() {int n, i, term 0, sum 0;printf("请输入一个数字(1~9): ");scanf("%d", &n);if (n <…

书生谱语-基于 InternLM 和 LangChain 搭建知识库

大语言模型与外挂知识库&#xff08;RAG&#xff09;的优缺点 RAG方案构建与优化 作业 在创建web_demo时&#xff0c;需要根据教程将服务器端口映射到本地端口&#xff0c;另外需要将链接的demo从服务器中复制出来&#xff0c;不要直接从服务器打开demo页面&#xff0c;不然会…

分布式事务详解

概述 随着互联网的发展&#xff0c;软件系统由原来的单体应用转变为分布式应用。分布式系统把一个单体应用拆分为可独立部署的多个服务&#xff0c;因此需要服务与服务之间远程协作才能完成事务操作。这种分布式系统下不同服务之间通过远程协作完成的事务称之为分布式事务&…

c# 拼音 帮助类

public class PinYinHelper { #region 获取汉字对应的拼音 /// <summary> /// 获取汉字对应的拼音 /// </summary> /// <param name"str"></param> /// <returns></returns> …

JavaScript中有哪些不同的数据类型

在 JavaScript 中&#xff0c;数据类型是一种用来表示数据的分类&#xff0c;它决定了我们可以对这个数据类型执行哪些操作。在 JavaScript 中有以下几种不同的数据类型&#xff1a; 基本数据类型 字符串 (String)&#xff1a;表示一组字符&#xff0c;可以使用引号&#xff08…

ElasticSearch级查询Query DSL上

目录 ES高级查询Query DSL match_all 返回源数据_source 返回指定条数size 分页查询from&size 指定字段排序sort 术语级别查询 Term query术语查询 Terms Query多术语查询 exists query ids query range query范围查询 prefix query前缀查询 wildcard query通…