SpringCloud Gateway 中GatewayFilterFactory介绍

2021-10-14 0 By admin

路由过滤器允许以某种方式修改【传入的HTTP请求】或【传出的HTTP响应】。过滤器可以限定作用在某些特定请求路径上。

一、网关过滤器工厂介绍

Spring Cloud Gateway包含许多内置的网关过滤器工厂。网关过滤器工厂接口有多个实现类,在每个 GatewayFilterFactory 实现类的 apply( T config) 方法里,都声明了一个实现 GatewayFilter 的内部类。
内置的过滤器工厂一共有22个,分别位于 org.springframework.cloud.gateway.filter.factory及org.springframework.cloud.gateway.filter.factory.rewrite包中。

1.1、网关过滤器工厂的生效配置

GatewayFilter 工厂同 Predicate工厂类似,都是在配置文件application.yml中配置,遵循了约定大于配置的思想。

在配置文件中只需要配置 GatewayFilter Factory的名称,而不需要写全部的类名。
比如 AddRequestHeaderGatewayFilterFactory 只需要在配置文件中写AddRequestHeader,而不是全部类名。
在配置文件中配置的GatewayFilter Factory最终都会相应的过滤器工厂类处理。

Spring Cloud Gateway 内置的过滤器工厂一览表如下:

Gateway Filtes 内置过滤器
Gateway Filtes 内置过滤器

1.2、GatewayFilterFactory 分类

过滤器有20多个实现类, 包括 header过滤器、 path类过滤器、 Hystrix过滤器和变更请求 URL 的过滤器, 还有参数和状态码等其他类型的过滤器。
内置的过滤器工厂有22个实现类,包括header过滤器、路径过滤器、Hystrix 过滤器、请求URL 变更过滤器,还有参数和状态码等其他类型的过滤器。
根据过滤器工厂的用途来划分,可以分为以下几种:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter和Hystrix。

GatewayFilterFactory 分类
GatewayFilterFactory 分类

1.3、GatewayFilterFactory 源码

由接口名称上的注解 @FunctionalInterface 可知,GatewayFilterFactory是一个函数式接口,其中 default 类型的方法 name 用来对过滤器进行标准化命名,apply 方法用于定义具体的过滤操作,泛型 C 是在各个实现类中的配置对象。

@FunctionalInterface
public interface GatewayFilterFactory<C> extends ShortcutConfigurable, Configurable<C> {
	String NAME_KEY = "name";
	String VALUE_KEY = "value";
	// useful for javadsl
	default GatewayFilter apply(Consumer<C> consumer) {
		C config = newConfig();
		consumer.accept(config);
		return apply(config);
	}
	default Class<C> getConfigClass() {
		throw new UnsupportedOperationException("getConfigClass() not implemented");
	}
	@Override
	default C newConfig() {
		throw new UnsupportedOperationException("newConfig() not implemented");
	}
	GatewayFilter apply(C config);
	default String name() {
		//TODO: deal with proxys
		return NameUtils.normalizeFilterFactoryName(getClass());
	}
	@Deprecated
	default ServerHttpRequest.Builder mutate(ServerHttpRequest request) {
		return request.mutate();
	}
}

1.4、GatewayFilterFactory 抽象实现类

GatewayFilter 抽象实现类
GatewayFilter 抽象实现类

由 GatewayFilterFactory 结构图可知,GatewayFilterFactory主要有三个抽象类:

1、AbstractGatewayFilterFactory 抽象类的子类:

  1. HystrixGatewayFilterFactory
  2. ModifyRequestBodyGatewayFilterFactory
  3. ModifyResponseBodyGatewayFilterFactory
  4. PrefixPathGatewayFilterFactory
  5. PreserveHostHeaderGatewayFilterFactory
  6. RedirectToGatewayFilterFactory
  7. RemoveRequestHeaderGatewayFilterFactory
  8. RemoveResponseHeaderGatewayFilterFactory
  9. RequestRateLimiterGatewayFilterFactory
  10. RetryGatewayFilterFactory
  11. RewritePathGatewayFilterFactory
  12. SaveSessionGatewayFilterFactory
  13. SecureHeadersGatewayFilterFactory
  14. SetPathGatewayFilterFactory
  15. SetStatusGatewayFilterFactory
  16. StripPrefixGatewayFilterFactory

2、AbstractNameValueGatewayFilterFactory(继承自AbstractGatewayFilterFactory) 抽象类的子类:

  1. AddRequestHeaderGatewayFilterFactory
  2. AddRequestParameterGatewayFilterFactory
  3. AddResponseHeaderGatewayFilterFactory
  4. SetRequestHeaderGatewayFilterFactory
  5. SetResponseHeaderGatewayFilterFactory

该抽象类用于提供通用的方法给键值对参数类型的网关过滤器,接收两个参数,如 AddRequestHeader 这种类型的过滤器。

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://example.org
        filters:
        - AddRequestHeader=X-Request-Foo, Bar

3、AbstractChangeRequestUriGatewayFilterFactory(继承自AbstractGatewayFilterFactory) 抽象类的子类:

  1. RequestHeaderToRequestUriGatewayFilterFactory

改变请求的 URI 过滤器,该过滤器通过方法 determineRequestUri( ServerWebExchange,T)实现改变请求URI的逻辑。

二、AddRequestHeader GatewayFilter Factory 介绍

2.1、引入相关的依赖

包括spring boot 版本2.0.5,spring Cloud版本Finchley,gateway依赖如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

2.2、配置文件

在工程的配置文件中,加入以下的配置:

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://httpbin.org:80/get
        filters:
        - AddRequestHeader=X-Request-Foo, Bar
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]
  1. 在上述的配置中,工程的启动端口为8081;
  2. 路由地址为http://httpbin.org:80/get,该router有AfterPredictFactory;
  3. 有一个filter为 AddRequestHeaderGatewayFilterFactory(约定写成AddRequestHeader);
  4. AddRequestHeader 过滤器工厂会在请求头加上一对请求头,名称为X-Request-Foo,值为Bar。

2.3、AddRequestHeaderGatewayFilterFactory 源码解读

public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
  @Override
  public GatewayFilter apply(NameValueConfig config) {
    return (exchange, chain) -> {
      ServerHttpRequest request = exchange.getRequest().mutate()
          .header(config.getName(), config.getValue())
          .build();
      return chain.filter(exchange.mutate().request(request).build());
    };
    }
}

由上面的代码可知,根据旧的 ServerHttpRequest 创建新的 ServerHttpRequest ,在新的 ServerHttpRequest 加了一个请求头,然后创建新的 ServerWebExchange,提交过滤器链继续过滤。
请求头中加入了X-Request-Foo这样的一个请求头,在配置文件中配置的AddRequestHeader过滤器工厂生效。
跟AddRequestHeader过滤器工厂类似的还有AddResponseHeader过滤器工厂。