SpringCloud 2023 Gateway的Filter配置介绍、类型、内置过滤器、自定义全局和单一内置过滤器

server/2024/10/17 21:34:53/

目录

  • 1. Filter介绍
  • 2. Filter类型
  • 3. 内置过滤器
    • 3.1 请求头(RequestHeader)相关GatewayFilter Factory
    • 3.2 请求参数(RequestParameter)相关GatewayFilter Factory
    • 3.3 回应头(ResponseHeader)相关GatewayFilter Factory
    • 3.4 前缀和路径相关GatewayFilter Factory
    • 3.5 Default Filters
  • 4. 自定义过滤器

1. Filter介绍

类似SpringMVC里面的的拦截器Interceptor,Servlet的过滤器。“pre”和“post”分别会在请求被执行前调用和被执行后调用,用来修改请求和响应信息。可以用来做请求鉴权、异常处理、记录接口调用时长

2. Filter类型

  1. 全局默认过滤器Global Filters:作用于所有的路由。gateway出厂默认已有的,直接用即可,不需要在配置文件中配置,实现GlobalFilter接口即可
  2. 单一内置过滤器GatewayFilter:也可以称为网关过滤器,这种过滤器主要是作用于单一路由或者某个路由分组
  3. 自定义过滤器

3. 内置过滤器

SpringCloud Gateway共提供了38种内置的GatewayFilter Factory。这里我们指讲解常用的

因为Request的相关操作,是一个前置过滤器,所以需要在最终提供服务的服务方Pay中实现如下controller,查看Request的详细情况

    @GetMapping(value = "/pay/gateway/filter")public ResultData<String> getGatewayFilter(HttpServletRequest request){Enumeration<String> headerNames = request.getHeaderNames();while(headerNames.hasMoreElements()) {String headName = headerNames.nextElement();String headValue = request.getHeader(headName);System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);}Enumeration<String> parameterNames = request.getParameterNames();while(parameterNames.hasMoreElements()) {String parameterName = parameterNames.nextElement();String parameterValue = request.getParameter(parameterName);System.out.println("请求参数名: " + parameterName +"\t\t\t"+"请求参数值: " + parameterValue);}return ResultData.success(null);}

3.1 请求头(RequestHeader)相关GatewayFilter Factory

  • AddRequestHeader GatewayFilter Factory:向请求头添加内容,需要两个参数,一个是请求头key ,一个是请求头value。如果请求头已经有配置文件的请求头key,则配置失效。gatewayServer的application配置如下。向网关发送http://localhost:8088/pay/gateway/filter请求,Pay的controller打印日志请求头名: headerkey 请求头值: headerValue,表示网关的filter添加request header成功
spring:cloud:gateway:routes:- id: payRoute                   uri: lb://payment             predicates:- Path=/pay/**              filters:- AddRequestHeader=headerKey,headerValue
  • RemoveRequestHeader GatewayFilter Factory:向请求头删除内容,需要一个参数,表示需要删除的请求头key
    • 配置: - RemoveRequestHeader=sec-fetch-site
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,Pay的controller没有打印sec-fetch-site请求头的日志,表示网关的filter删除request header成功
  • SetRequestHeader GatewayFilter Factory:修改请求头的内容,需要两个参数,一个是要修改的请求头key ,一个是要修改的请求头value。如果要修改的请求头key不存在,则进行添加
    • 配置: - SetRequestHeader=sec-fetch-mode,my-navigate
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,Pay的controller打印日志请求头名: sec-fetch-mode 请求头值: my-navigate,表示网关的filter修改request header成功

3.2 请求参数(RequestParameter)相关GatewayFilter Factory

  • AddRequestParameter GatewayFilter Factory:向请求参数添加内容,需要两个参数,一个是参数key ,一个是参数value。如果请求参数已经有配置文件的参数key,则配置失效
    • 配置:- AddRequestParameter=username,lily
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,Pay的controller打印日志请求参数名: username 请求参数值: lily,表示网关的filter添加request parameter成功
  • RemoveRequestParameter GatewayFilter Factory:向请求参数删除内容,需要一个参数,表示需要删除的参数key
    • 配置:- RemoveRequestParameter=userid
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter?userid=666请求,Pay的controller没有打印userid请求参数的日志,表示网关的filter删除request parameter成功

3.3 回应头(ResponseHeader)相关GatewayFilter Factory

  • AddResponseHeader GatewayFilter Factory:向响应头添加内容,需要两个参数,一个是响应头key ,一个是响应头value。如果配置文件的响应头key和已经有的响应头key一样,则配置继续有效

    • 配置:- AddResponseHeader=responseKey,responseValue
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,浏览器的Headers的Response Headers有responsekey: responseValue,表示网关的filter添加response header成功
  • SetResponseHeader GatewayFilter Factory:修改响应头的内容,需要两个参数,一个是要修改的响应头key ,一个是要修改的响应头value。如果要修改的响应头key不存在,则进行添加

    • 配置: - SetResponseHeader=Date,2099-12-31
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,浏览器的Headers的Response Headers的Date为date: 2099-12-31,表示网关的filter修改response header成功
  • RemoveResponseHeader GatewayFilter Factory:向响应头删除内容,需要一个参数,表示需要删除的响应头key

    • 配置: - RemoveResponseHeader=Content-Type
    • 效果:向网关发送http://localhost:8088/pay/gateway/filter请求,浏览器的Headers的Response Headers没有Content-Type这个响应header了,表示网关的filter删除response header成功

3.4 前缀和路径相关GatewayFilter Factory

  • PrefixPath GatewayFilter Factory:给请求自动添加路径前缀。gatewayServer的配置文件配置如下。向网关发送http://localhost:8088/gateway/filter请求,符合predicates的要求,则通过filter给路径添加前缀/pay,最终请求的路径是payment的http://localhost:8001/pay/gateway/filter。请求正常执行,表示网关的filter添加路径前缀成功
spring:cloud:gateway:routes:- id: payRoute                   uri: lb://payment             predicates:- Path=/gateway/**              filters:- PrefixPath=/pay
  • SetPath GatewayFilter Factory:对请求路径进行修改。gatewayServer的配置文件配置如下。向网关发送http://localhost:8088/pay2/gateway/filter请求,符合predicates的要求,则通过filter修改路径为/pay/gateway/filter,最终请求的路径是payment的http://localhost:8001/pay/gateway/filter。请求正常执行,表示网关的filter修改路径成功
spring:cloud:gateway:routes:- id: payRoute                   uri: lb://payment             predicates:- Path=/pay2/{segment1}/{segment2}  filters:- PrefixPath=/pay/{segment1}/{segment2}  # 不支持通配符**。{segment}表示占位符,需要保持上下一致
  • RedirectTo GatewayFilter Factory:将路径重定向到某个页面。gatewayServer的配置文件配置如下。向网关发送http://localhost:8088/pay/gateway/filter请求,符合predicates的要求,然后页面重定向打开的是百度的页面
spring:cloud:gateway:routes:- id: payRoute                   uri: lb://payment             predicates:- Path=/pay/**filters:- RedirectTo=302, http://www.baidu.com

3.5 Default Filters

前面讲过的GatewayFilter Factory都可以使用,但作用于所有的route。gateway配置文件配置如下。向网关发送http://localhost:8088/pay/gateway/filter请求,Pay的controller打印日志请求头名: headerkey 请求头值: headerValue,表示网关的filter添加request header成功

spring:cloud:gateway:default-filters:- AddRequestHeader=headerKey,headerValueroutes:- id: payRoute                   uri: lb://payment             predicates:- Path=/pay/**           

4. 自定义过滤器

4.1 自定义全局过滤器

  • 需求:统计每个请求的耗时时长
  • 思路:不管是在每个接口中进行统计;还是通过AOP + 反射形成注解然后进行使用。都会对业务代码形成入侵,可以通过自定义全局过滤器来实现
  • 步骤1:新建类MyGlobalFilter并实现GlobalFilter,Ordered两个接口。实现代码如下:
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;@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {private static final String BEGIN_VISIT_TIME = "begin_visit_time";@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 先记录下访问接口的开始时间exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());// 进行放行,然后通过then获取到接口的响应return chain.filter(exchange).then(Mono.fromRunnable(() -> {Long beginVisitTime = exchange.getAttribute(BEGIN_VISIT_TIME);if (beginVisitTime != null) {System.out.println("接口主机: " + exchange.getRequest().getURI().getHost());System.out.println("接口端口: " + exchange.getRequest().getURI().getPort());System.out.println("接口URL: " + exchange.getRequest().getURI().getPath());System.out.println("接口URL参数: " + exchange.getRequest().getURI().getRawQuery());System.out.println("访问接口时长: " + (System.currentTimeMillis() - beginVisitTime) + "ms");System.out.println("###################################################");}}));}@Overridepublic int getOrder() {// 数字越小优先级越高return 0;}
}
  • 步骤2:无需配置application.yml
  • 测试:向网关发送http://localhost:8088/pay/gateway/filter请求,gatewayServer打印日志如下:
接口主机: localhost
接口端口: 8088
接口URL: /pay/gateway/filter
接口URL参数: null
访问接口时长: 313ms
###################################################

4.2 自定义单一内置过滤器

4.2.1 实现步骤:

  1. gatewayServer项目中新建自定义Filter Factory类MyGatewayFilterFactory。类名的后缀必须是GatewayFilterFactory。所以这里创建的是一个My Gateway Filter
  2. 类继承AbstractGatewayFilterFactory
  3. 实现无参构造器,调用父类的构造器
  4. 实现一个配置类MyGatewayFilterFactory.Config,定义需要添加前缀的reponse header key responseHeaderKey和给reponse header value添加的前缀responseHeaderPrefixValue
  5. 重写父类的apply方法,实现匹配reponse header的key和给reponse header的value添加前缀的逻辑
  6. 重写父类的shortcutFieldOrder方法,让其支持shortcut语法

4.2.2 实现代码如下:

import lombok.Getter;
import lombok.Setter;
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.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Arrays;
import java.util.List;@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {public MyGatewayFilterFactory() {super(MyGatewayFilterFactory.Config.class);}public static class Config {@Getter@Setterprivate String responseHeaderKey;      // 需要添加前缀的reponse header key@Getter@Setterprivate String responseHeaderPrefixValue;  // 给reponse header value添加前缀}@Overridepublic GatewayFilter apply(MyGatewayFilterFactory.Config config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return chain.filter(exchange).then(Mono.fromRunnable(() -> {// 获取reponse headersHttpHeaders responseHeaders = exchange.getResponse().getHeaders();responseHeaders.keySet().forEach(responseHeaderKey -> {// 如果reponse header的key和配置文件中的key相同,则给response hadear的value添加前缀if (responseHeaderKey.equals(config.getResponseHeaderKey())) {responseHeaders.set(responseHeaderKey, config.getResponseHeaderPrefixValue() + responseHeaders.getFirst(responseHeaderKey));}});}));// exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);// return exchange.getResponse().setComplete();}};}@Overridepublic List<String> shortcutFieldOrder() {// 列表: [responseHeaderKey, responseHeaderValue]return Arrays.asList("responseHeaderKey", "responseHeaderValue");}}

4.2.3 application.yml配置

全部展开语法配置如下:

            - name: Myargs:responseHeaderKey: DateresponseHeaderPrefixValue: test_

快捷语法配置: - My=Date,test_

4.2.4 测试

向网关发送http://localhost:8088/pay/gateway/filter请求。浏览器的Headers的Response Headers的Date为date: test_Mon, 12 Aug 2024 09:31:44 GMT,表示自定义单一内置过滤器成功


http://www.ppmy.cn/server/131218.html

相关文章

通过修改注册表来提高导出图像的分辨率(PPT尝试)

通过修改注册表来提高 PowerPoint 导出图片的分辨率&#xff0c;可以导致导出的图片尺寸大于您期望的 1920 x 1080 像素。例如&#xff0c;将 ExportBitmapResolution 设置为 300 DPI&#xff0c;可能会导致输出图像的尺寸变得非常大&#xff0c;比如 10240 x 5760 像素。这是因…

FLINK SQL时间属性

Flink三种时间属性简介 在Flink SQL中&#xff0c;时间属性是一个核心概念&#xff0c;它主要用于处理与时间相关的数据流。Flink支持三种时间属性&#xff1a;事件时间&#xff08;event time&#xff09;、处理时间&#xff08;processing time&#xff09;和摄入时间&#…

回溯法与迭代法详解:如何从手机数字键盘生成字母组合

在这篇文章中&#xff0c;我们将详细介绍如何基于手机数字键盘的映射&#xff0c;给定一个仅包含数字 2-9 的字符串&#xff0c;输出它能够表示的所有字母组合。这是一个经典的回溯算法问题&#xff0c;适合初学者理解和掌握。 问题描述 给定一个数字字符串&#xff0c;比如 …

云原生、云计算、虚拟化概念概述

&#xff08;带着批评阅读&#xff0c;不对的请评论区补充&#xff09; 1、出现年代前后顺序 虚拟化------>云计算------>云原生 2、虚拟化 虚拟化侧重描述实现&#xff0c;最开始的技术是模拟、hook指令执行软件程序&#xff0c;后续出现了半虚拟化、CPU硬件提供虚拟化…

常见的负载均衡

1.常见的负载均衡服务 负载均衡服务是分布式系统中用于分配网络流量和请求的关键组件&#xff0c;它可以帮助提高应用程序的可用性、可扩展性和响应速度。以下是一些常用的负载均衡服务&#xff1a; Nginx&#xff1a;一个高性能的Web服务器和反向代理&#xff0c;广泛用于实现…

Spark第一天

MapReduce过程复习 Spark由五部分组成 RDD五大特征 1、 Spark -- 代替MapReduce <<<<< scala是单机的&#xff0c;spark是分布式的。>>>>> 开源的分布式计算引擎 可以快速做计算 -- 因为可以利用内存来做一些计算 (1) 分为5个库(模块) : 1、…

【OceanBase诊断调优】—— 错误码 5065 和 5066 的区别

适用版本&#xff1a;V2.1.x、V2.2.x、V3.1.x、V3.2.x 5065 与 5066 是两个近似的报错。 OB_ERR_QUERY_INTERRUPTED(-5065): Message: Query execution was interrupted。 含义为执行中断, 例如终端执行 SQL 过程中按 ctrlc 终止 SQL 执行会报 -5065。 OB_ERR_SESSION_INTER…

原来!给我一首歌的时间,真的可以搞定Vue的计算属性computed ,以及如何区分watch监视属性

目录 1. 什么是Vue的计算属性呢&#xff1f; 2. 如何区分computed 和 watch&#xff1f; 3. computed 完整示例1 4. computed 完整示例2 1. 什么是Vue的计算属性呢&#xff1f; Vue的计算属性&#xff08;Computed Properties&#xff09;是Vue框架中一个非常重要的特性&a…