Spring Cloud Gateway自定义过滤器

自定义全局过滤器

相关面试题:统计接口调用耗时,如何落地,谈谈设计思路?

自定义统计接口耗时的全局过滤器

  • https://docs.spring.io/spring-cloud-gateway/docs/4.0.9/reference/html/#gateway-combined-global-filter-and-gatewayfilter-ordering
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** 自定义全局过滤器,实现GlobalFilter和Ordered接口,统计接口耗时** @author gengduc@qq.com* @since 2024-03-09*/
@Component
@Slf4j
public class CustomGlobalFilter implements GlobalFilter, Ordered {public static final String BEGIN_VISIT_TIME = "begin_visit_time";@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {/* 1、保存请求开始时间 */exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());return chain.filter(exchange).then(Mono.fromRunnable(() -> {/* 2、获取请求开始时间 */Long beginTime = exchange.getAttribute(BEGIN_VISIT_TIME);if (beginTime != null) {/* 3、计算接口耗时 */log.info("==========访问接口耗时统计==========");log.info("访问接口主机: " + exchange.getRequest().getURI().getHost());log.info("访问接口端口: " + exchange.getRequest().getURI().getPort());log.info("访问接口路径: " + exchange.getRequest().getURI().getPath());log.info("访问接口参数: " + exchange.getRequest().getURI().getQuery());log.info("访问接口时间: " + (System.currentTimeMillis() - beginTime) + "ms");log.info("==============E N D==============");}}));}/*** 设置过滤器的优先级,值越小优先级越高** @return 优先级*/@Overridepublic int getOrder() {return 0;}
}

设计思路:

  1. 实现GlobalFilterOrderd接口。
  2. 实现getOrder()方法,方法返回值代表过滤器的优先级,值越小,优先级越高。
  3. 实现filter()方法。方法接收两个参数:ServerWebExchange和GatewayFilterChain。ServerWebExchange是一个接口,它提供了对HTTP请求-响应交互的全面访问。GatewayFilterChain是一个接口,它提供了对下一个过滤器的访问。
    1. 首先,方法将当前的系统时间(请求开始的时间)存储在ServerWebExchange的属性中。这是通过调用exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis())实现的。
    2. 然后,方法调用chain.filter(exchange)来处理请求。这个调用会将请求传递给过滤器链中的下一个过滤器。如果没有更多的过滤器,那么请求将被发送到目标服务。
    3. 当请求被处理完毕后,then方法会被调用。这个方法接收一个Runnable参数,这个参数是一个无参数的函数,它会在请求被处理完毕后被执行。
    4. 在这个Runnable函数中,首先从ServerWebExchange的属性中获取请求开始的时间。然后,计算处理请求所花费的时间(当前的系统时间减去请求开始的时间)。最后,将这些信息记录在日志中。

自定义网关过滤器

要自定义网关过滤器,参考Spring Cloud Gateway自带的网关过滤器实现。

自定义网关过滤器的步骤如下:

  1. 新建类名CustomGatewayFilterFactory(类名需要以GatewayFilterFactory结尾),并继承AbstractGatewayFilterFactory抽象类。
  2. 新建CustomGatewayFilterFactory.Config静态内部类,这个Config类就是我们自定义的过滤器配置
  3. 重写apply()方法,处理自定义逻辑,返回GatewayFilter对象。
  4. 重写shortcutFieldOrder()方法,使yml配置支持快捷配置
  5. 空参构造函数调用了父类的构造函数,传入了Config类的Class对象。
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Arrays;
import java.util.List;/*** @author gengduc@qq.com* @since 2024-03-09*/
@Component
@Slf4j
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {private static final String STATUS_KEY = "status";public CustomGatewayFilterFactory() {super(Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList(STATUS_KEY);}@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("请求进入自定义网关过滤器,请求路径为: {}", exchange.getRequest().getURI().getPath());log.info("提示: 合法请求中请求参数必须包含\"custom\"参数, 否则请求将被拦截");ServerHttpRequest request = exchange.getRequest();if (request.getQueryParams().containsKey("custom")) {log.info("请求参数中包含custom参数, 请求合法, 放行");log.info("请求参数中custom参数的值为: {}", request.getQueryParams().get("custom"));return chain.filter(exchange);} else {log.info("请求参数中不包含custom参数, 请求非法, 拦截");exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);return exchange.getResponse().setComplete();}}};}@Setter@Getterpublic static class Config {// 自定义配置属性private String status;}
}

apply()方法是AbstractGatewayFilterFactory的抽象方法,子类需要实现这个方法来创建过滤器。在这个方法中,返回了一个新的GatewayFilter对象。

在返回的GatewayFilter对象中,重写了filter方法。这个方法在每个请求被处理之前都会被调用。在这个方法中,首先打印了一些日志,然后检查请求参数中是否包含"custom"这个键。如果包含,那么就继续处理请求,并打印出"custom"参数的值;如果不包含,那么就设置响应的状态码为BAD_REQUEST,并结束请求的处理。

spring:application:name: gateway-service # 网关服务名称cloud:consul:host: 47.120.52.144 # Consul服务地址port: 8500 # Consul服务端口discovery:prefer-ip-address: true # 服务注册时优先使用IP地址而不是主机名service-name: ${spring.application.name} # 在Consul中注册的服务名称heartbeat:enabled: true # 启用心跳检测,定期检查服务健康状态gateway:routes:- id: order-routeuri: http://localhost:8001predicates:- Path=/pay/get/1filters:- Custom=custom

浏览器访问地址:

  • http://localhost:9527/pay/get/1?custom=1✅
  • http://localhost:9527/pay/get/1✖️

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

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

相关文章

python中def简介及用法

什么是def&#xff1f; def是python中的一个关键字&#xff0c;它用于定义一个函数。函数是一段具有特定功能的代码&#xff0c;可以被重复调用&#xff0c;从而提高代码的复用性和可读性。 如何使用def&#xff1f; def的基本语法如下&#xff1a; def 函数名(参数列表):#…

MYSQL | 数据库到底是怎么来的?

“以史为鉴&#xff0c;可以让我们更深刻地理解现在&#xff0c;预见未来。” 要想知道一件东西是怎么发生的, 我们不妨把时间拨回关系型数据库被提出前后来探索。在信息技术飞速发展的今天&#xff0c;回望数据库管理系统的演进之路&#xff0c;我们可以深刻理解到技术进步如…

Go语言数据结构(二)堆/优先队列

文章目录 1. container中定义的heap2. heap的使用示例3. 刷lc应用堆的示例 更多内容以及其他Go常用数据结构的实现在这里&#xff0c;感谢Star&#xff1a;https://github.com/acezsq/Data_Structure_Golang 1. container中定义的heap 在golang中的"container/heap"…

ffmpeg批量旋转视频

1、新建一个txt文件&#xff0c;并复制如下代码进入&#xff0c;然后保存。 echo off & titlecd /d %~dp0md rotatefor %%a in (*.mp4) do (ffmpeg -i "%%~sa" -y -vf "transpose1" -q:v 1 "rotate\%%~na.mp4")pause2、把文件后缀修改为bat…

STC8G1K08串口通讯

/***豆腐干下位机测试 L573 CODE 3919 2021 1 25***/ /***STC8G1K08 三段时间控制程序 电机自动启停***/ #include <REG52.H> //下降一段设置 #include <intrins.h> //保压时间 #in…

js-判断变量是否定义

if (typeof myVar undefined) {// myVar (未定义) 或 (已定义但未初始化) } else {// myVar (已定义和已初始化) } 参考 https://www.cnblogs.com/redFeather/p/17662966.html

yield代码解释

目录 我们的post请求爬取百度翻译的代码 详细解释 解释一 解释二 再说一下callback 总结 发现了很多人对存在有yield的代码都不理解&#xff0c;那就来详细的解释一下 我们的post请求爬取百度翻译的代码 import scrapy import jsonclass TestpostSpider(scrapy.Spider):…

Linux网络套接字之预备知识

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、预备知识 1.理解源IP地址和目的IP地址 …

表单进阶(4)-下拉菜单

select支持&#xff1a; 1.size显示几个 2.multiple同时选中多个 如果用select&#xff0c;option必须设置value值 option支持的属性&#xff1a; 1.value&#xff0c;提供给后端的值 2.selected&#xff0c;默认选中 <!DOCTYPE html> <html lang"en"> …

编程示例: 矩阵的多项式计算以javascript语言为例

编程示例: 矩阵的多项式计算以javascript语言为例 国防工业出版社的《矩阵理论》一书中第一章第8个习题 试计算2*A^8-3*A^5A^4A^2-4I A[[1,0,2],[0,-1,1],[0,1,0]] 代码如下 <html> <head> <title> 矩阵乘法 </title> <script srcset.js ><…

【解读】OWASP 大语言模型(LLM)安全测评基准V1.0

大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;是指参数量巨大、能够处理海量数据的模型, 此类模型通常具有大规模的参数&#xff0c;使得它们能够处理更复杂的问题&#xff0c;并学习更广泛的知识。自2022 年以来&#xff0c;LLM技术在得到了广泛的应…

Selenium WebDriver API 中涉及的一些常用方法和类

Selenium WebDriver API 是 Selenium 提供的一组方法和类&#xff0c;用于控制浏览器和操作 Web 元素。这些 API 提供了丰富的功能&#xff0c;包括但不限于&#xff1a; 1. **查找元素**&#xff1a;通过不同的定位方式&#xff08;如ID、Class Name、XPath等&#xff09;在页…

C++学习随笔(1)——初识篇

前面一章我们简单介绍了一下C与C语言之间的关系&#xff0c;本章就让我们来正式入门学习一下C吧&#xff01; 目录 1.第一个C程序 2.头文件 &#xff08;1&#xff09;简介 &#xff08;2&#xff09;常见的头文件&#xff1a; 2. 命名空间 2.1 命名空间定义 2.2 命名空…

leetcode 热题 100_搜索二维矩阵

题解一&#xff1a; 二叉搜索树&#xff1a;从矩阵右上角观察&#xff0c;结构类似二叉搜索树&#xff0c;因此可以用类似的解法来做。具体做法是双指针从右上角开始&#xff0c;向左下角逐步搜索&#xff0c;如果当前值比目标值大&#xff0c;则向下移动&#xff0c;如果当前值…

了解 HTTPS 中间人攻击:保护你的网络安全

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

mybatis-plus整合spring boot极速入门

使用mybatis-plus整合spring boot&#xff0c;接下来我来操作一番。 一&#xff0c;创建spring boot工程 勾选下面的选项 紧接着&#xff0c;还有springboot和依赖我们需要选。 这样我们就创建好了我们的spring boot&#xff0c;项目。 简化目录结构&#xff1a; 我们发现&a…

Qt 实现诈金花的牌面值分析工具

诈金花是很多男人最爱的卡牌游戏 , 每当你拿到三张牌的时候, 生活重新充满了期待和鸟语花香. 那么我们如果判断手中的牌在所有可能出现的牌中占据的百分比位置呢. 这是最终效果: 这是更多的结果: 在此做些简单的说明: 炸弹(有些地方叫豹子) > 同花顺 > 同花 > 顺…

Day27:安全开发-PHP应用TP框架路由访问对象操作内置过滤绕过核心漏洞

目录 TP框架-开发-配置架构&路由&MVC模型 TP框架-安全-不安全写法&版本过滤绕过 思维导图 PHP知识点 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技…

安卓提示风险解决源码搭建教程

一&#xff0e;环境 1.安装Nginx 2.安装Tomcat8.5 3. 安装Mysql5.7 二&#xff0e;修改app已生成的文件下载地址 1.打开编辑config.properties 2.填写你的ip&#xff0c;端口不用修改 三&#xff0e;启动教程 启动命令&#xff1a;sh.start.sh 源码下载链接:https://p…

计算机网络 IP多播的概念

多播是让源主机一次发送的单个分组可以抵达用一个组地址表示的若干目的地址&#xff0c;即&#xff0c;一对多的通信。在互联网上进行的多播&#xff0c;称为IP多播。 与单播相比&#xff0c;在一对多的通信中&#xff0c;多播可以大大节约网络资源。 IP多播地址&#xff0c;…