Spring Cloud Gateway GatewayFilter的使用

一、GatewayFilter的作用

路由过滤器允许我们以某种方式修改进来的Request和出去的Response。Spring Cloud Gateway内置很多的 GatewayFilter

二、Spring Cloud Gateway内置的 GatewayFilter

1、AddRequestHeader

1、描述

1、用于向下游服务 添加 请求头,
2、支持 uri variables

2、参数

1、name:向下游服务传递请求头的 key
2、value:向下游服务传递请求头的 value

3、示例

1、方式一、添加一个固定的请求头

spring:
cloud:
nacos:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddRequestHeader=x-token,xxxxx

表示会向下游服务传递一个 x-token 的请求头,值是 xxxxx

2、配合 uri variables 添加动态请求头

spring:
cloud:
gateway:
routes:
- id: product-provider-02
uri: lb://product-provider
predicates:
- Path=/product/findOne/{productId}
filters:
- AddRequestHeader=x-token,xxxxx-{productId}

表示会向下游服务传递一个 x-token 的请求头,值是 xxxxx-匹配上的productId的值

2、AddRequestParameter

1、描述

用于向下游服务 添加一个请求参数

2、参数

1、name:添加的参数 key
2、value:添加的参数 value,可以支持 Path或Host 中的 uri variables

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddRequestParameter=username,zhangsan

向下游服务增加一个 username = zhangsan 的请求参数

3、AddResponseHeader

1、描述

向下游的响应中增加一个 响应头。

2、参数

1、name:添加的响应头的 key
2、value:添加的响应头的 value,可以支持 Path或Host 中的 uri variables

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddResponseHeader=encryption,false

向下游服务响应增加一个 encryption = false 的响应头

4、DedupeResponseHeader

1、描述

移除重复的请求头

2、参数

1、name:需要移除的重复的响应头,多个以 空格 分隔
2、strategy:重复时,移除的策略,默认是RETAIN_FIRST,即保留第一个头

  1. RETAIN_FIRST:保留第一个值
  2. RETAIN_LAST:保留最后一个值
  3. RETAIN_UNIQUE:保留所有的不重复的值

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- DedupeResponseHeader=x-token Access-Control-Allow-Credentials Access-Control-Allow-Origin,RETAIN_FIRST

移除上方指定的重复的响应头,并且保留第一个出现的。

5、MapRequestHeader

1、描述

fromHeader 参数的值 追加到 toHeader 参数中。

  1. fromHeader 在 header 中不存在,那么没有什么影响。
  2. fromHeader 存在
  3.  toHeader 存在,那么往配置中 toHeader 对应的 header 中追加 fromHeader对应的值
  4. toHeader 不存在,那么往 header 中增加一个header ,key: 配置中的toHeader的值,value: fromHeader 在header中的值

2、参数

1、fromHeader:从请求参数中获取header的值
2、toHeader:向header中设置一个 header, key是toheader的值,value 是 fromHeader的值

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- MapRequestHeader=from-header,x-token

即会向 request 中增加一个 key 为 x-token 的header ,值为 header 中 from-header 对应的值。(存在多种情况,参考描述

6、Prefix

1、描述

为匹配到的路由,在转发到下游服务时,增加一个前缀prefix

2、参数

1、prefix:需要增加的路径前缀

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/findOne
filters:
- PrefixPath=/product

访问 http://网关ip:port/findOne ⇒ 转发到下游服务地址 http://product-provider/product/findOne 增加了一个前缀。

7、PreserveHostHeader

1、描述

它表示在Spring Cloud Gateway转发请求的时候,保持客户端的Host信息不变,然后将它传递到下游服务器中。

2、参数

没有参数

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- PreserveHostHeader

8、RemoveRequestHeader

1、描述

移除请求头中的参数

2、参数

1、name:需要移除的请求头

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveRequestHeader=x-token

9、RemoveResponseHeader

1、描述

移除响应头

2、参数

1、name:需要移除的响应头

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveResponseHeader=x-token

9、RemoveRequestParameter

1、描述

移除请求参数,往下游服务传递时,此参数就没有来

2、参数

1、name:需要移除的请求参数

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveRequestParameter=password

10、RewritePath

1、描述

根据正则表达式,执行路径重写

2、参数

1、regexp:匹配的正则表达式
2、replacement:需要替换成的字符串
注意:
1、在yml配置中 $ 需要写成 $\
2、路径替换规则是: path.replaceAll(regexp,replacement)

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/admin/product/findOne
filters:
- RewritePath=/admin(?<segment>/?.*), $\{segment} # 当访问/admin/product/findOne 将会替换成 /product/findOne

页面上访问 /admin/product/findOne ⇒ 到达下游服务的路径是 /product/findOne

11、StripPrefix

1、描述

移除路径前缀,比如访问: /admin/aa/bb/cc 实际的下游服务器地址是 /bb/cc 则可以使用这个实现

2、参数

1、parts:请求的路径按照/分隔后,需要跳过的部分,从1开始。

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/admin/product/findOne
filters:
- StripPrefix=1 # 当访问/admin/product/findOne 将会替换成 /product/findOne

页面上访问 /admin/product/findOne ⇒ 到达下游服务的路径是 /product/findOne

12、RequestSize

1、描述

配置请求体的大小,当请求体过大时,将会返回 413 Payload Too Large

2、参数

1、maxSize:请求体的大小

3、示例

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- name: RequestSize
args:
maxSize: 1B

此处需要通过 filters[index].args.maxSize 配置,否则不生效。

13、ModifyRequestBody

1、描述

修改传递到下游服务 RequestBody 的值,比如我们所有的经过网关的服务,到达下游服务时,都需要将 用户当前的用户名和数据权限传递下去,此时就可以使用这个。

2、需求:

修改原始服务的参数,增加usernameroles参数传递到下游服务。

3、路由配置,只可通过 Java 代码来配置

@Configuration
public class RouteConfig { @Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("product-provider", predicateSpec -> predicateSpec.path("/product/modifyRequestBody")
.filters(gatewayFilterSpec -> gatewayFilterSpec.modifyRequestBody(String.class, Map.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> {
Map<String, Object> params = new HashMap<>(16);
params.put("old", s);
params.put("username", "v_huan");
params.put("roles", "ROLE_ADMIN");
return Mono.just(params);
})).uri("lb://product-provider")).build();
}
}

14、ModifyResponseBody

1、 描述

修改下游服务返回的ResponseBody的值,和上方的RequestBody类似,此处不在处理。

15、更多的 GatewayFilterFactory

在代码中查看 GatewayFilterFactory 的子类即可。

三、配置默认拦截器

1、描述

默认拦截器,对所有的路由都会生效。

2、配置方法

配置文件中使用 spring.cloud.gateway.default-filters 配置

3、示例

spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin

四、全局过滤器

当某个请求被路由匹配时,那么所有的全局过滤器(GlobalFilter)和路由匹配到的 GatewayFilter会组合成一个过滤器链,排序规则是通过 Spring 的 Ordered 来排序。

GlobalFilterprepost2个执行阶段,优先级越高 pre 阶段执行越早, post阶段执行越迟。

编写一个全局过滤器需要实现 GlobalFilter 接口。
注意:

GlobalFilter的用来在未来的版本中可能会发生改变。

1、ForwardRoutingFilter

ForwardRoutingFilter 用来处理 forward:///localendpoint 请求。

2、LoadBalancerClientFilter

LoadBalancerClientFilter 用来处理 lb://service-name 这样的请求

spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**


设置 spring.cloud.loadbalancer.ribbon.enabled=false

3、The Websocket Routing Filter

处理 websocket 请求

spring:
cloud:
gateway:
routes:
# SockJS route
- id: websocket_sockjs_route
uri: http://localhost:3001
predicates:
- Path=/websocket/info/**
# Normal Websocket route
- id: websocket_route
uri: [ws|wss]://localhost:3001
predicates:
- Path=/websocket/**

4、更多全局过滤器

https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#global-filters

五、自定义全局过滤器

  1. 实现 GlobalFilter 接口和 Ordered 接口
  2. 加入到 Spring 管理
  3. 代码实现
@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
log.info("进入了全局过滤器,path:[{}]", path); // 修改 request
ServerHttpRequest request = exchange.getRequest().mutate().header("x-token", "123456").build(); return chain.filter(exchange.mutate().request(request).build());
} /**
* 指定全局过滤器执行的顺序
*
* @return
*/
@Override
public int getOrder() {
return 0;
}
}

六、编写一个 GatewayFilter

1、实现 GatewayFilterFactory 或者继承 AbstractGatewayFilterFactory<C>
2、继承AbstractGatewayFilterFactory<C> 类时,构造方法中需要调用 super(C.class)
3、重写 shortcutFieldOrder方法,定义配置文件中字段的位置
4、编写的过滤器类必须要以 GatewayFilterFactory结尾
5、自定义过滤器的名字为,GatewayFilterFactory前面的字符,比如 TokenGatewayFilterFactory,那么过滤器名字是 Token
5、功能实现:过滤器实现,从请求中获取一个参数的值,打印出来

1、Java代码实现

@Component
@Slf4j
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config> { public TokenGatewayFilterFactory() {
super(Config.class);
} @Override
public List<String> shortcutFieldOrder() {
return Lists.newArrayList("tokenName");
} @Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
log.info("每次路由匹配到会执行");
String tokenName = config.getTokenName();
log.info("从配置文件中获取到的 tokenName 的值=[{}].", tokenName);
String value = exchange.getRequest().getQueryParams().getFirst(tokenName);
log.info("从请求中获取到的token value 是:[{}]", value);
return chain.filter(exchange);
};
} @Data
public static class Config {
private String tokenName;
}
}

2、配置文件中的写法

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- Token=gateway-token

七、其它的配置

1、获取当前命令的路由

 // 1、获取当前匹配上的路由
Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
String routeId = route.getId();
Map<String, Object> metadata = route.getMetadata();
log.info("routeId:[" + routeId + "]" + "metadata:[" + metadata + "]");

2、过滤器的执行顺序

3、配置超时时间

1、配置全局超时时间(注意单位)

spring:
cloud:
gateway:
httpclient:
# 全局的连接超时,单位毫秒
connect-timeout: 1000
# 全局的响应超时,需要符合java.time.Duration规范
response-timeout: 3s

2、配置每个路由的超时时间(注意单位)

spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
metadata:
# 单个路由配置响应超时,单位毫秒
response-timeout: 200
# 单个路由配置连接超时,单位毫秒
connect-timeout: 200

4、输出gateway调试日志

1、输出 netty 的 access log

需要使用设置如下参数,注意是 JVM 的参数

-Dreactor.netty.http.server.accessLogEnabled=true

2、设置日志级别 debug or trace

logging:
level:
org.springframework.cloud.gateway: trace
org.springframework.http.server.reactive: trace
org.springframework.web.reactive: trace
org.springframework.boot.autoconfigure.web: trace
reactor.netty: trace

八、网关错误的处理

实现 WebExceptionHandler 接口,在里面出现错误逻辑。需要注意 指定该接口的 order 否则可能被别的处理了,自己的不生效。
返回完成信号:表示错误处理完成
返回错误信息:交由下个处理器处理。
eg:

/**
* 异常处理器,需要注意 @Order 指定执行的顺序
*
* @author huan.fu 2020/11/15 - 14:47
*/
@Component
@Slf4j
@Order(Integer.MIN_VALUE)
public class GatewayExceptionHandler implements WebExceptionHandler { @Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
log.info("发生了异常", ex);
String errorMsg = "{\"code\":500,\"msg\":\"服务器内部错误\"}"; ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
DataBuffer dataBuffer = response.bufferFactory().wrap(errorMsg.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(dataBuffer));
}
}

九、完整代码

https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway-filter

十、参考链接

https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories

Spring Cloud Gateway GatewayFilter的使用的更多相关文章

  1. Spring Cloud Gateway 之 AddRequestHeader GatewayFilter Factory

    今天我们来学习下GatewayFilter Factory,中文解释就是过滤器工厂. 官方文档对GatewayFilter Factory的介绍: Route filters allow the mo ...

  2. Spring Cloud Gateway(九):网关过滤器 GatewayFilter

    本文基于 spring cloud gateway 2.0.1 1.简介 GatewayFilter 网关过滤器用于拦截并链式处理web请求,可以实现横切的与应用无关的需求,比如:安全.访问超时的设置 ...

  3. 从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析

    API 网关 API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题 ...

  4. 简单尝试Spring Cloud Gateway

    简单尝试Spring Cloud Gateway 简介 Spring Cloud Gateway是一个API网关,它是用于代替Zuul而出现的.Spring Cloud Gateway构建于Sprin ...

  5. spring cloud gateway的stripPrefix配置

    序 本文主要研究下spring cloud gateway的stripPrefix配置 使用zuul的配置 zuul: routes: demo: sensitiveHeaders: Access-C ...

  6. api网关揭秘--spring cloud gateway源码解析

    要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux. 1.gateway 和zuul对比 I am the au ...

  7. spring cloud gateway - RequestRateLimiter

    1. Official website 5.7 RequestRateLimiter GatewayFilter Factory The RequestRateLimiter GatewayFilte ...

  8. Spring Cloud Gateway服务网关

    原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gatewa ...

  9. spring cloud gateway之filter篇

    转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在上一篇文章详细的介绍了Gateway的Predict,Predict决定了请求由哪一个路由处理,在路由 ...

随机推荐

  1. charles 抓包修改app页面数据

    1,首先给手机安装Charles证书,安装官方的来,在无线网配置项目,输入手动代理地址,后开启飞行模式刷新网络, 2,在浏览器输入chls.pro/ssl 下载并安装证书,此时电脑端charles 会 ...

  2. JVM-调优-命令

    目录 jps 命令格式 option参数 示例 jstat 命令格式 参数 option 参数总览 option 参数详解 -class -compiler -gc -gccapacity -gcut ...

  3. 引人遐想,用 Python 获取你想要的 “某个人” 摄像头照片

    仅用来学习,希望给你们有提供到学习上的作用. 1.安装库 需要安装python3.5以上版本,在官网下载即可.然后安装库opencv-python,安装方式为打开终端输入命令行. 2.更改收件人和发件 ...

  4. PHP中的MySQLi扩展学习(四)mysqli的事务与预处理语句

    对于 MySQLi 来说,事务和预处理语句当然是它之所以能够淘汰 MySQL(原始) 扩展的资本.我们之前也已经学习过了 PDO 中关于事务和预处理语句相关的内容.所以在这里,我们就不再多讲理论方面的 ...

  5. PHP的LZF压缩扩展工具

    这次为大家带来的是另外一个 PHP 的压缩扩展,当然也是非常冷门的一种压缩格式,所以使用的人会比较少,而且在 PHP 中提供的相关的函数也只是对字符串的编码与解码,并没有针对文件的操作.因此,就像 B ...

  6. 对象赋值在PHP中到底是不是引用?

    之前的文章中,我们说过变量赋值的问题,其中有一个问题是对象在进行变量赋值的时候,直接就是引用赋值.那么到底真实情况是怎样呢? 之前变量赋值的文章 PHP的变量赋值 对象引用测试 在继续深入的学习PHP ...

  7. 如何使用SQL的备份文件(.bak)恢复数据库

    出于很多情况,数据库只剩下.bak文件,想要恢复数据库,找了很多资料才知道可以这样!!!!! 个人觉得图片教程更有意义,请看步骤: 1.选中"数据库" 右击 选择"还原数 ...

  8. Jenkins操作手册 - 巨详细,一篇足矣!

    一.继续集成相关概念 1.1.什么是持续集成? 随着软件开发复杂度的不断提高,团队开发成员间如何更好的协同工作以确保软件开发的质量已经成为开发过程中不可回避的问题.尤其是近年来敏捷开发在软件领域越来越 ...

  9. Jmeter系列(25)- 常用逻辑控制器 (4) | Include控制器Include Controller

    认识 Include Controller Include Controller :译为包含控制器,用来添加 Test Fragment(测试片段).具体是什么意思呢,我们先来了解下 Test Fra ...

  10. spring入门3-jdbcTemplate简单使用和声明式事务

    1.JdbcTemplate简单使用 1.1.引入相关依赖包 <dependency> <groupId>mysql</groupId> <artifactI ...