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

SpringCloudAlibaba Gateway(二)详解-内置Predicate、Filter及自定义Predicate、Filter

Predicate(断言)

​ Predicate(断言),用于进行判断,如果返回为真,才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现,直接配置即生效,当然也支持自定义路由断言工厂。

内置路由断言工厂实现

​ SpringCloudGateway路由断言工厂实现有很多,可以帮助开发者完成不同的功能。

  • AfterRoutePredicateFactory:设定日期参数,允许在指定日期时间之后的请求通过
- After=2020-01-20T17:42:47.789+08:00[Asia/Shanghai]
  • BeforeRoutePredicateFactory:设定日期参数,允许在指定日期时间之前的请求通过
- Before=2020-01-20T17:42:47.789+08:00[Asia/Shanghai]
  • BetweenRoutePredicateFactory:设定日期区间,使用逗号分隔,表示允许在时间段内的请求通过
- Between=2020-01-20T17:42:47.789+08:00[Asia/Shanghai],2023-02-20T17:42:47.789+08:00[Asia/Shanghai]
  • CookieRoutePredicateFactory:设置Cookie的名称和cookie值的正则表达式,判断请求是否含有该Cookie名称且值与正则表达式相匹配
- Cookie=chocolate, ch.p
  • HeaderRoutePredicateFactory:设定请求头名称和请求头值的正则表达式,判断请求是否含有该请求头,且值与正则相匹配
- Header=X-Request-Id, \d+
  • HostRoutePredicateFactory:设定host,判断请求的host是否满足条件。
- Host=**.test.com
  • MethodRoutePredicateFactory:设定请求方式,只允许满足请求类型的请求方式通过
- Method=GET
  • PathRoutePredicateFactory:设定路由规则,判断请求地址是否满足设定的路径规则
- Path=/shop/**
  • QueryRoutePredicateFactory:设定参数名称和参数值的正则,判断请求是否含有该参数,且值符合正则规则
- Query=name,z.
  • RemoteAddrRoutePredicateFactory:设置IP地址段,判断请求的主机地址是否满足条件
- RemoteAddr=10.xxx.xxx.xxx/24

注意:这里是一个IP的地址段,不是单纯的IP地址

  • WeightRoutePredicateFactory:设定权重分组和权重值,同一个分组名的路由根据权重值进行转发
routes:- id: user_group1uri: http://test1.compredicates:- Path=/user/**- Weight=user_grp,8		# 设置user_grp组,80%请求进入user_group1- id: user_group2uri: http://test2.compredicates:- Path=/user/**- Weight=user_grp,2		# 设置user_grp组,20%请求进入user_group2

内置断言实例

指定POST请求

server:port: 8083spring:application:name: gateway   # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由,可配置多个- id: user_route  # 路由id,唯一即可,默认UUIDuri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1  # 路由优先级,默认0,越低优先级越高predicates:- Path=/user/**   # 断言,匹配规则- Method=POST     # 表示需要POST请求

使用CMD测试下:当使用GET请求时,gateway直接打回,告知沒有找到

curl localhost:8083/user/findById?id=1
{"timestamp":"2023-08-26T00:24:35.884+00:00","path":"/user/findById","status":404,"error":"Not Found","message":null,"requestId":"0c70f6cf-1"}

使用POST请求,正确访问(-X POST表示使用POST请求方式)

curl -X POST  localhost:8083/user/findById?id=1
Zhangsan

不指定为POST请求时,请求会被404.

使用Query路由断言

使用Query路由断言工厂,且设置参数名为id,正则表达式\d+(一个或多个数字)

server:port: 8083spring:application:name: gateway   # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由,可配置多个- id: user_route  # 路由id,唯一即可,默认UUIDuri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1  # 路由优先级,默认0,越低优先级越高predicates:- Path=/user/**   # 断言,匹配规则- Query=id, \d+   # 参数名id,且值是数字(一位或多位)

使用cmd调用测试,使用非数字时,被告知404

curl localhost:8083/user/findById?id=ss
{"timestamp":"2023-08-26T00:29:38.252+00:00","path":"/user/findById","status":404,"error":"Not Found","message":null,"requestId":"bc0fe260-3"}

使用数字,符合正则,正确访问

curl localhost:8083/user/findById?id=1
Zhangsan

自定义路由断言工厂

​ 在实际的项目开发中,开发者也可以创建自定义的路由断言工厂,进行自己的业务扩展。实际上前面所有的断言工厂都是继承自AbstractRoutePredicateFactory,并且配置是-Method时那么类就是MethodRoutePredicateFactory要创建自定义断言工厂,我们也需要集成自此类,然后重写自己的扩展即可。

实例:创建自定义断言工厂,只允许id为1~1000的请求通过

  • 编写自定义的断言工厂CustomRoutePredicateFactory,那么配置时就是-Custom
@Component  // 交给Spring管理
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {public static final String[] KEY_ARRAY = {"minId", "maxId"};    // 对象属性public CustomRoutePredicateFactory() {        // 构造函数,需要给父类初始化一个配置类super(CustomRoutePredicateFactory.Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList(KEY_ARRAY);}@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() { // 设置断言逻辑@Overridepublic String toString() {return String.format("minId:%d, maxId:%d", config.getMinId(), config.getMaxId());}@Overridepublic boolean test(ServerWebExchange exchange) {// 得到idString id = exchange.getRequest().getQueryParams().getFirst("id");if (id != null) {int numberId = Integer.parseInt(id);// 当 请求的id是在此范围内,返回truereturn numberId >= config.getMinId() && numberId <= config.getMaxId();}return false;}};}@Validatedpublic static class Config {   // 配置类(注意这里是静态类,否则属性是注入不进去的)private Integer minId;  // 最小idprivate Integer maxId;  // 最大idpublic Integer getMinId() {return minId;}public void setMinId(Integer minId) {this.minId = minId;}public Integer getMaxId() {return maxId;}public void setMaxId(Integer maxId) {this.maxId = maxId;}}
}

yml配置

server:port: 8083spring:application:name: gateway   # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由,可配置多个- id: user_route  # 路由id,唯一即可,默认UUIDuri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1  # 路由优先级,默认0,越低优先级越高predicates:- Path=/user/**   # 断言,匹配规则- Custom=1,1000   # 设置值为1,1000

测试,当id不在范围内

curl localhost:8083/user/findById?id=0
{"timestamp":"2023-08-26T01:09:02.567+00:00","path":"/user/findById","status":404,"error":"Not Found","message":null,"requestId":"61dcf9de-1"}

在范围内

curl localhost:8083/user/findById?id=1
Zhangsan

没问题!~

Filter过滤器

​ 做过J2EE开发的应该不会对这个词感到陌生。在SpringCloudGateway中的过滤器也有类似的功能,都可以在请求和响应间做一些自定义的逻辑。

​ Gateway的过滤器又分为局部全局,而且同样有内置和自定义。

内置局部过滤器

局部过滤器只针对当前路由的

  • AddRequestHeader:设定Header的值,为原始的请求添加Header
- AddRequestHeader=X-Request-token, 123456
  • AddRequestParameter:设定参数名和值,为原始请求添加参数
- AddRequestParameter=name, zhangsan
  • AddResponseHeader:设定Header的值,为响应添加Header
- AddResponseHeader=token, 123456
  • DedupeResponseHeader:设定去重的Header名称和去重策略,删除响应头中的重复值
- DedupeResponseHeader=Access-Control-Allow-Credentinals Access-Control-Allow-Origin

多个Header使用空格分隔,去重策略:RETAIN_FIRST(保留第一个)RETAIN_LAST(保留最后一个)RETAIN_UNIQUE(保留所有的唯一值)

  • PrefixPath:给请求加前缀,为原始请求添加路径
- PrefixPath=/userPrefix
  • RedirectTo:设定HTTP状态码和URL,将原始请求重定向到指定的URL
- RedirectTo=302, https://test.com
  • RewritePath:设定原始路径(支持正则)和重写路径(支持正则),重写原始路径
- RewritePath=/user/findById, /user/test
  • StripPrefix:设定要拦截的路径数量,用于修改原始路
- StripPrefix=1	# 如果请求是 /user/findById,那么会被拦截为 /findById
  • RequestSize:设定请求包大小(单位字节,默认5MB)
filters:- name: RequestSizeargs:maxSize: 5000000

自定义局部过滤器

还是按照前面提到的,id在1~1000内允许访问,否则直接拒绝。同路由断言工厂类似,是配置+GatewayFilterFactory的命名然后继承AbstractGatewayFilterFactory

写一个UserGatewayFilterFactory的类

@Component
public class UserGatewayFilterFactory extends AbstractGatewayFilterFactory<UserGatewayFilterFactory.Config> {private static final String[] KEY_ARRAYS = {"minId", "maxId"};public UserGatewayFilterFactory() { // 构造函数super(UserGatewayFilterFactory.Config.class);}@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {// 获取id String id = exchange.getRequest().getQueryParams().getFirst("id");if (id != null) {int number = Integer.parseInt(id);if (number >= config.getMinId() && number <= config.getMaxId()) {// 放行return chain.filter(exchange);}}byte[] bytes = ("您不能访问"+id+"用户的数据").getBytes(StandardCharsets.UTF_8);DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(bytes);// 设定HTTP状态码exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 返回友好提示return exchange.getResponse().writeWith(Flux.just(wrap));};}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList(KEY_ARRAYS);}public static class Config {private Integer minId;private Integer maxId;public Integer getMinId() {return minId;}public void setMinId(Integer minId) {this.minId = minId;}public Integer getMaxId() {return maxId;}public void setMaxId(Integer maxId) {this.maxId = maxId;}}
}

yml配置

server:port: 8083spring:application:name: gateway   # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由,可配置多个- id: user_route  # 路由id,唯一即可,默认UUIDuri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1  # 路由优先级,默认0,越低优先级越高predicates:- Path=/user/**   # 断言,匹配规则filters:- User=1,1000		# 设置id为1~1000的过滤

测试一手,id空或id并不在范围内

curl localhost:8083/user/findById
您不能访问null用户的数据curl localhost:8083/user/findById?id=2000
您不能访问2000用户的数据

成功测试

curl localhost:8083/user/findById?id=1
Zhangsan

全局过滤器

全局过滤器在前面的文章中也大概了解过几个,如openFeign的超时时间等,其他的也基本类似,用的不是很多。

通常情况下自定义全局过滤器是比较常用的了,下面看一个案例,客户端访问时的token认证功能的。

处理类需要实现GlobalFilter和Ordered接口,重写方法

@Component
public class TokenFilter implements GlobalFilter, Ordered { // 自定义全局过滤private final static String token = "123456";   // 这里做个模拟token@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 从请求头中拿到tokenString token = exchange.getRequest().getHeaders().getFirst("token");if (token != null) {if (token.equals(TokenFilter.token)) {  // 如果请求头中带的token是123456 那么放行// 放行return chain.filter(exchange);}}byte[] bytes = ("您不能访问" + exchange.getRequest().getPath() + "地址").getBytes(StandardCharsets.UTF_8);DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(bytes);exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 返回友好提示return exchange.getResponse().writeWith(Flux.just(wrap));}@Overridepublic int getOrder() { // 排序,值越小,优先级越高(说的是过滤器的优先级,当有多个过滤器时,order可以控制它们的执行优先级)return 0;}
}

下面用工具测试一下,token

在这里插入图片描述
在这里插入图片描述

相关文章:

SpringCloudAlibaba Gateway(二)详解-内置Predicate、Filter及自定义Predicate、Filter

Predicate(断言) ​ Predicate(断言)&#xff0c;用于进行判断&#xff0c;如果返回为真&#xff0c;才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现&#xff0c;直接配置即生效&#xff0c;当然也支持自定义路由断言工厂。 内置路由断言工厂实现 ​ SpringClo…...

调用chat-gpt

调用chat-gpt 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifact…...

Element组件浅尝辄止6:Dialog 对话框组件

Dialog 对话框组件&#xff1a;在保留当前页面状态的情况下&#xff0c;告知用户并承载相关操作。 大白话就是弹窗组件&#xff0c;日常开发中比较常见 1.怎样使用&#xff1f; //触发方式 <el-button type"text" click"dialogVisible true">打开&…...

Bert和LSTM:情绪分类中的表现

一、说明 这篇文章的目的是评估和比较 2 种深度学习算法&#xff08;BERT 和 LSTM&#xff09;在情感分析中进行二元分类的性能。评估将侧重于两个关键指标&#xff1a;准确性&#xff08;衡量整体分类性能&#xff09;和训练时间&#xff08;评估每种算法的效率&#xff09;。…...

【面试经典150题】跳跃游戏

题目链接 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 1 < nums…...

【Rust】003-基础语法:流程控制

【Rust】003-基础语法&#xff1a;流程控制 文章目录 【Rust】003-基础语法&#xff1a;流程控制一、概述二、if 表达式1、语法格式2、多个3、获取表达式的值 三、循环1、loop&#xff1a;无限循环&#xff0c;可跳出无限循环跳出循环返回值 2、while&#xff1a;条件循环&…...

0829【综述】面向时空数据的区块链研究综述

摘要:时空数据包括时间和空间2个维度,常被应用于物流、供应链等领域。传统的集中式存储方式虽然具有一定的便捷性,但不能充分满足时空数据存储及查询等要求,而区块链技术采用去中心化的分布式存储机制,并通过共识协议来保证数据的安全性。研究现有区块链1.0、2.0和以Block-DAG为…...

MySQL高级篇(SQL优化、索引优化、锁机制、主从复制)

目录 0 存储引擎介绍1 SQL性能分析2 常见通用的JOIN查询 SQL执行加载顺序七种JOIN写法3 索引介绍 3.1 索引是什么3.2 索引优劣势3.3 索引分类和建索引命令语句3.4 索引结构与检索原理3.5 哪些情况适合建索引3.6 哪些情况不适合建索引4 性能分析 4.1 性能分析前提知识4.2 Expla…...

YOLOV8模型使用-检测-物体追踪

这个最新的物体检测模型&#xff0c;很厉害的样子&#xff0c;还有物体追踪的功能。 有官方的Python代码&#xff0c;直接上手试试就好&#xff0c;至于理论&#xff0c;有想研究在看论文了╮(╯_╰)╭ 简单介绍 YOLOv8 中可用的模型 YOLOv8 模型的每个类别中有五个模型用于检…...

springmvc:设置后端响应给前端的json数据转换成String格式

设置spring-mvc.xml: xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:context"http://www.springframework.org/schema/context"xmlns:xsi"http://www.w…...

Mac安装brew、mysql、redis

mac安装brew mac安装brewmac安装mysql并配置开机启动mac安装redis并配置开机启动 mac安装brew 第一步&#xff1a;执行. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"第二步&#xff1a;输入开机密码 第三…...

MLC-LLM 部署RWKV World系列模型实战(3B模型Mac M2解码可达26tokens/s)

0x0. 前言 我的 ChatRWKV 学习笔记和使用指南 这篇文章是学习RWKV的第一步&#xff0c;然后学习了一下之后决定自己应该做一些什么。所以就在RWKV社区看到了这个将RWKV World系列模型通过MLC-LLM部署在各种硬件平台的需求&#xff0c;然后我就开始了解MLC-LLM的编译部署流程和…...

Unity 之 参数类型之值类型参数的用法

文章目录 基本数据类型结构体结构体的进一步补充 总结&#xff1a; 当谈论值类型参数时&#xff0c;我们可以从基本数据类型和结构体两个方面详细解释。值类型参数指的是以值的形式传递给函数或方法的数据&#xff0c;而不是引用。 基本数据类型 基本数据类型的值类型参数&…...

VScode远程连接主机

一、前期准备 1、Windows安装VSCode&#xff1b; 2、在VSCode中安装PHP Debug插件&#xff1b; 3、安装好Docker 4、在容器中安装Xdebug ①写一个展现phpinfo的php文件 <?php phpinfo(); ?>②在浏览器上打开该文件 ③复制所有信息丢到Xdebug: Installation instr…...

【iOS】属性关键字

文章目录 前言一、深拷贝与浅拷贝1、OC的拷贝方式有哪些2. OC对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝&#xff1f;3. 自定义对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝&#xff1f;4. 判断当前的深拷贝的类型&#xff1f;(区别是单层深拷贝还是完全深拷贝…...

【计算机基础】Git从安装到使用,详细每一步!扩展Github\Gitlab

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

深入了解Docker镜像操作

Docker是一种流行的容器化平台&#xff0c;它允许开发者将应用程序及其依赖项打包成容器&#xff0c;以便在不同环境中轻松部署和运行。在Docker中&#xff0c;镜像是构建容器的基础&#xff0c;有些家人们可能在服务器上对docker镜像的操作命令不是很熟悉&#xff0c;本文将深…...

嵌入式开发-单片机学习介绍

一、单片机入门篇 单片机的定义和历史 单片机是一种集成了微处理器、存储器、输入输出接口和其他功能于一体的微型计算机&#xff0c;具有高度的集成性和便携性。单片机的历史可以追溯到20世纪70年代&#xff0c;随着微电子技术的不断发展&#xff0c;单片机逐渐成为了工业控…...

5、Spring之Bean生命周期源码解析(销毁)

Bean的销毁过程 Bean销毁是发送在Spring容器关闭过程中的。 在Spring容器关闭时,比如: AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService) context.getBean("userSe…...

开发多点触控MFC应用程序

当下计算机变得越来越智能化&#xff0c;越来越无所不能&#xff0c;触摸屏的普及只是时间问题了。 虽然鼠标和键盘不会很快就离开人们的视野&#xff0c;毕竟人们使用鼠标跟键盘已经成为一种习惯&#xff0c;但是处理信息或者说操作计算机的其他方法也层出不穷——比如触控技术…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

基于小程序老人监护管理系统源码数据库文档

摘 要 近年来&#xff0c;随着我国人口老龄化问题日益严重&#xff0c;独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长&#xff0c;随之而来的是日益突出的老年人问题&#xff0c;尤其是老年人的健康问题&#xff0c;尤其是老年人产生健康问题后&…...

CKA考试知识点分享(2)---ingress

CKA 版本&#xff1a;1.32 第二题是涉及ingress相关。本文不是题目&#xff0c;只是为了学习相关知识点做的实验。 1. 环境准备 需要准备一套K8S集群。 1.1 安装ingress-nginx 下载deploy文件&#xff1a; wget -O controller-v1.12.2.yaml https://raw.githubusercontent…...

可视化图解算法48:有效括号序列

牛客网 面试笔试 TOP101 | LeetCode 20. 有效的括号 1. 题目 描述 给出一个仅包含字符(,),{,},[和],的字符串&#xff0c;判断给出的字符串是否是合法的括号序列 括号必须以正确的顺序关闭&#xff0c;"()"和"()[]{}"都是合法的括号序列&…...