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

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

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

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

相关文章

Java注解和反射

注解(Java.Annotation) 什么是注解&#xff08;Annotation&#xff09;&#xff1f; Annotation是从JDK5.0开始引入的新技术 Annotation的作用: 不是程序本身&#xff0c;可以对程序作出解释(这一点和注释(comment)没什么区别)可以被其他程序(比如:编译器等)读取Annotation的…

ChatGPT插件的优缺点

虽然西弗吉尼亚大学的研究人员看到了最新的官方ChatGPT插件——名为“代码解释器”&#xff08; Code Interpreter&#xff09;的教育应用潜力&#xff0c;但他们也发现&#xff0c;对于使用计算方法处理针对癌症和遗传疾病的定向治疗的生物数据的科学家来说&#xff0c;这款插…

20230901工作心得:IDEA列操作lambda表达式加强版用法

今天是中小学开学时间&#xff0c;亦是9月的开始&#xff0c;继续努力。 今日收获较大的有四个地方&#xff0c;先说这四点。 1、IDEA列操作 使用场景&#xff1a;需要批量将Excel表格里的数据插入到数据库中&#xff0c;此时需要写大量的insert SQL语句。 比如像这样的&am…

解码注意力Attention机制:从技术解析到PyTorch实战

目录 引言历史背景重要性 二、注意力机制基础概念定义组件 注意力机制的分类举例说明 三、注意力机制的数学模型基础数学表达式注意力函数计算权重 数学意义举例解析 四、注意力网络在NLP中的应用机器翻译代码示例 文本摘要代码示例 命名实体识别&#xff08;NER&#xff09;代…

WireShark流量抓包详解

目录 Wireshark软件安装Wireshark 开始抓包示例Wireshakr抓包界面介绍WireShark 主要界面 wireshark过滤器表达式的规则 Wireshark软件安装 软件下载路径&#xff1a;wireshark官网。按照系统版本选择下载&#xff0c;下载完成后&#xff0c;按照软件提示一路Next安装。 Wire…

ICCV 2023 | 利用双重聚合的Transformer进行图像超分辨率

导读 本文提出一种同时利用图像空间和通道特征的 Transformer 模型&#xff0c;DAT&#xff08;Dual Aggregation Transformer&#xff09;&#xff0c;用于图像超分辨&#xff08;Super-Resolution&#xff0c;SR&#xff09;任务。DAT 以块间和块内的双重方式&#xff0c;在空…

企业工程项目管理系统源码-专注项目数字化管理-Java工程管理-二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

用于设计和分析具有恒定近心点半径的低推力螺旋轨迹研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

用Kubernetes(k8s)的ingress部署https应用

用Kubernetes的ingress部署https应用 环境准备Ingress安装域名证书准备 部署应用通过ingress暴露应用根据ssl证书生成对应的secret创建ingress暴露部署的应用确认自己安装了ingress创建ingress 访问你暴露的应用 环境准备 Ingress安装 我之前有一片文章写的是用ingress暴露应…

树和二叉树基础

引言&#xff1a; 树是一种非线性的结构&#xff0c;也是由一个一个的结点构成。 树的一些基本概念&#xff1a; 节点的度&#xff1a;一个节点含有的子树的个数称为该节点的度&#xff1b;如上图&#xff1a;A的度为6 叶节点或终端节点&#xff1a;度为0的节点称为叶节点。…

【LeetCode75】第四十四题 省份数量

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们一个二维数组&#xff0c;表示城市之间的连通情况&#xff0c;连在一起的城市为一个省份&#xff0c;问我们一共有多少个省份。 这…

cocos creator配置终端调试

在launch.json里添加"preLaunchTask":“CocosCreator compile” 在cocos creator里选择开发者&#xff0c;visual studio code工作流&#xff0c;选择添加编译任务。 添加 settings.json {"files.exclude":{"**/.git": true,"**/.DS_Sto…

【大数据】Flink 详解(六):源码篇 Ⅰ

Flink 详解&#xff08;六&#xff09;&#xff1a;源码篇 Ⅰ 55、Flink 作业的提交流程&#xff1f;56、Flink 作业提交分为几种方式&#xff1f;57、Flink JobGraph 是在什么时候生成的&#xff1f;58、那在 JobGraph 提交集群之前都经历哪些过程&#xff1f;59、看你提到 Pi…

2023年7月京东打印机行业品牌销售排行榜(京东运营数据分析)

鲸参谋监测的京东平台7月份打印机行业销售数据已出炉&#xff01; 7月份&#xff0c;打印机市场呈现下滑趋势。根据鲸参谋平台的数据可知&#xff0c;当月京东平台打印机的销量为48万&#xff0c;环比下降约28%&#xff0c;同比下降约18%&#xff1b;销售额为4亿&#xff0c;环…

【云原生】Kubernetes容器编排工具

目录 1. K8S介绍 1.1 k8s的由来 下载地址 1.2 docker编排与k8s编排相比 1.3 传统后端部署与k8s 的对比 传统部署 k8s部署 ​2. k8s的集群架构与组件 &#xff08;1&#xff09; Kube-apiserver &#xff08;2&#xff09;Kube-controller-manager &#xff08;3&a…

(数字图像处理MATLAB+Python)第十一章图像描述与分析-第三、四节:几何表述和形状描述

文章目录 一&#xff1a;几何描述&#xff08;1&#xff09;像素间几何关系A&#xff1a;邻接与连通B&#xff1a;距离 &#xff08;2&#xff09;像素间几何特征A&#xff1a;位置B&#xff1a;方向C&#xff1a;尺寸 &#xff08;3&#xff09;程序 二&#xff1a;形状描述&a…

SPI3+DMA外设驱动-TFTLCD初始化

前言 &#xff08;1&#xff09;本系列是基于STM32的项目笔记&#xff0c;内容涵盖了STM32各种外设的使用&#xff0c;由浅入深。 &#xff08;2&#xff09;小编使用的单片机是STM32F105RCT6&#xff0c;项目笔记基于小编的实际项目&#xff0c;但是博客中的内容适用于各种单片…

13.动态渲染侧边栏

为什么要动态渲染&#xff1f; 比如我们现在需要以下侧边栏的数据&#xff1a; 如果一个个的去写标签会很麻烦&#xff0c;发现导航栏中的数据分为两类&#xff0c;一类是一级导航&#xff0c;另一位是二级导航&#xff08;有子页&#xff09;&#xff0c;因此直接写两个函数判…

ClickHouse进阶(六):副本与分片-2-Distributed引擎

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…

如何使用SQL系列 之 了解SQL中的约束规则

简介 在设计数据库时&#xff0c;有时可能需要对某些列中允许的数据设置限制。例如&#xff0c;如果你要创建一张表来保存摩天大楼的信息&#xff0c;你可能希望在保存每座大楼高度的列中禁止使用负值。 关系型数据库管理系统(RDBMS)允许你使用约束来控制哪些数据被添加到表中…