gatewayfilter详解_聊聊spring cloud gateway的GatewayFilter

本文主要研究一下spring cloud gateway的GatewayFilter

GatewayFilter

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/GatewayFilter.java

/**

* Contract for interception-style, chained processing of Web requests that may

* be used to implement cross-cutting, application-agnostic requirements such

* as security, timeouts, and others. Specific to a Gateway

*

* Copied from WebFilter

*

* @author Rossen Stoyanchev

* @since 5.0

*/

public interface GatewayFilter extends ShortcutConfigurable {

String NAME_KEY = "name";

String VALUE_KEY = "value";

/**

* Process the Web request and (optionally) delegate to the next

* {@code WebFilter} through the given {@link GatewayFilterChain}.

* @param exchange the current server exchange

* @param chain provides a way to delegate to the next filter

* @return {@code Mono} to indicate when request processing is complete

*/

Mono filter(ServerWebExchange exchange, GatewayFilterChain chain);

}

如注释所说,主要用于类似切面的非功能性需求,比如安全、超时控制等。其直接的实现类为OrderedGatewayFilter、ModifyResponseGatewayFilter、GatewayFilterAdapter

OrderedGatewayFilter

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java

public class OrderedGatewayFilter implements GatewayFilter, Ordered {

private final GatewayFilter delegate;

private final int order;

public OrderedGatewayFilter(GatewayFilter delegate, int order) {

this.delegate = delegate;

this.order = order;

}

public GatewayFilter getDelegate() {

return delegate;

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

return this.delegate.filter(exchange, chain);

}

@Override

public int getOrder() {

return this.order;

}

@Override

public String toString() {

final StringBuilder sb = new StringBuilder("OrderedGatewayFilter{");

sb.append("delegate=").append(delegate);

sb.append(", order=").append(order);

sb.append('}');

return sb.toString();

}

}

实现了Order接口

ModifyResponseGatewayFilter

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java

public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {

private final Config config;

public ModifyResponseGatewayFilter(Config config) {

this.config = config;

}

@Override

@SuppressWarnings("unchecked")

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {

@Override

public Mono writeWith(Publisher extends DataBuffer> body) {

ResolvableType inElementType = ResolvableType.forClass(config.getInClass());

ResolvableType outElementType = ResolvableType.forClass(config.getOutClass());

MediaType contentType = exchange.getResponse().getHeaders().getContentType();

Optional> reader = getHttpMessageReader(codecConfigurer, inElementType, contentType);

Optional> writer = getHttpMessageWriter(codecConfigurer, outElementType, null);

if (reader.isPresent() && writer.isPresent()) {

ResponseAdapter responseAdapter = new ResponseAdapter(body, getDelegate().getHeaders());

Flux> modified = reader.get().read(inElementType, responseAdapter, config.getInHints())

.cast(inElementType.resolve())

.flatMap(originalBody -> Flux.just(config.rewriteFunction.apply(exchange, originalBody)))

.cast(outElementType.resolve());

return getDelegate().writeWith(

writer.get().write((Publisher)modified, outElementType, null, getDelegate(),

config.getOutHints())

);

}

// TODO: error? log?

return getDelegate().writeWith(body);

}

@Override

public Mono writeAndFlushWith(Publisher extends Publisher extends DataBuffer>> body) {

return writeWith(Flux.from(body)

.flatMapSequential(p -> p));

}

};

return chain.filter(exchange.mutate().response(responseDecorator).build());

}

@Override

public int getOrder() {

return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;

}

}

主要用于修改response

GatewayFilterAdapter

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/handler/FilteringWebHandler.java

private static class GatewayFilterAdapter implements GatewayFilter {

private final GlobalFilter delegate;

public GatewayFilterAdapter(GlobalFilter delegate) {

this.delegate = delegate;

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

return this.delegate.filter(exchange, chain);

}

@Override

public String toString() {

final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");

sb.append("delegate=").append(delegate);

sb.append('}');

return sb.toString();

}

}

将GlobalFilter转为GatewayFilter的适配器

GatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java

@FunctionalInterface

public interface GatewayFilterFactory extends ShortcutConfigurable, Configurable {

String NAME_KEY = "name";

String VALUE_KEY = "value";

// useful for javadsl

default GatewayFilter apply(Consumer consumer) {

C config = newConfig();

consumer.accept(config);

return apply(config);

}

default Class 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();

}

}

spring cloud gateway采用工厂模式来生成GatewayFilter,可以看到这里定义了apply方法,根据config来生成GatewayFilter。GatewayFilterFactory有几个抽象类,分别是AbstractGatewayFilterFactory、AbstractNameValueGatewayFilterFactory(继承了AbstractGatewayFilterFactory)、AbstractChangeRequestUriGatewayFilterFactory。

AbstractGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java

public abstract class AbstractGatewayFilterFactory

extends AbstractConfigurable implements GatewayFilterFactory {

@SuppressWarnings("unchecked")

public AbstractGatewayFilterFactory() {

super((Class) Object.class);

}

public AbstractGatewayFilterFactory(Class configClass) {

super(configClass);

}

public static class NameConfig {

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

}

它的直接实现类如下:

HystrixGatewayFilterFactory

ModifyRequestBodyGatewayFilterFactory

ModifyResponseBodyGatewayFilterFactory

PrefixPathGatewayFilterFactory

PreserveHostHeaderGatewayFilterFactory

RedirectToGatewayFilterFactory

RemoveRequestHeaderGatewayFilterFactory

RemoveResponseHeaderGatewayFilterFactory

RequestRateLimiterGatewayFilterFactory

RetryGatewayFilterFactory

RewritePathGatewayFilterFactory

SaveSessionGatewayFilterFactory

SecureHeadersGatewayFilterFactory

SetPathGatewayFilterFactory

SetStatusGatewayFilterFactory

StripPrefixGatewayFilterFactory

AbstractNameValueGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractNameValueGatewayFilterFactory.java

public abstract class AbstractNameValueGatewayFilterFactory extends AbstractGatewayFilterFactory {

public AbstractNameValueGatewayFilterFactory() {

super(NameValueConfig.class);

}

public List shortcutFieldOrder() {

return Arrays.asList(GatewayFilter.NAME_KEY, GatewayFilter.VALUE_KEY);

}

@Validated

public static class NameValueConfig {

@NotEmpty

protected String name;

@NotEmpty

protected String value;

public String getName() {

return name;

}

public NameValueConfig setName(String name) {

this.name = name;

return this;

}

public String getValue() {

return value;

}

public NameValueConfig setValue(String value) {

this.value = value;

return this;

}

@Override

public String toString() {

return new ToStringCreator(this)

.append("name", name)

.append("value", value)

.toString();

}

}

}

将泛型限定为AbstractNameValueGatewayFilterFactory.NameValueConfig,其实现类如下:

AddRequestHeaderGatewayFilterFactory

AddRequestParameterGatewayFilterFactory

AddResponseHeaderGatewayFilterFactory

SetRequestHeaderGatewayFilterFactory

SetResponseHeaderGatewayFilterFactory

AbstractChangeRequestUriGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractChangeRequestUriGatewayFilterFactory.java

/**

* This filter changes the request uri by

* {@link #determineRequestUri(ServerWebExchange, T)} logic.

*

* @author Toshiaki Maki

*/

public abstract class AbstractChangeRequestUriGatewayFilterFactory

extends AbstractGatewayFilterFactory {

private final int order;

public AbstractChangeRequestUriGatewayFilterFactory(Class clazz, int order) {

super(clazz);

this.order = order;

}

public AbstractChangeRequestUriGatewayFilterFactory(Class clazz) {

this(clazz, RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1);

}

protected abstract Optional determineRequestUri(ServerWebExchange exchange,

T config);

public GatewayFilter apply(T config) {

return new OrderedGatewayFilter((exchange, chain) -> {

Optional uri = this.determineRequestUri(exchange, config);

uri.ifPresent(u -> {

Map attributes = exchange.getAttributes();

attributes.put(GATEWAY_REQUEST_URL_ATTR, u);

});

return chain.filter(exchange);

}, this.order);

}

}

通过GATEWAY_REQUEST_URL_ATTR设置新的uri,其直接实现类为

RequestHeaderToRequestUriGatewayFilterFactory(通过header的值来设定uri)

GatewayFilterFactory.apply

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java

private List loadGatewayFilters(String id, List filterDefinitions) {

List filters = filterDefinitions.stream()

.map(definition -> {

GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());

if (factory == null) {

throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName());

}

Map args = definition.getArgs();

if (logger.isDebugEnabled()) {

logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName());

}

Map properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);

Object configuration = factory.newConfig();

ConfigurationUtils.bind(configuration, properties,

factory.shortcutFieldPrefix(), definition.getName(), validator);

GatewayFilter gatewayFilter = factory.apply(configuration);

if (this.publisher != null) {

this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));

}

return gatewayFilter;

})

.collect(Collectors.toList());

ArrayList ordered = new ArrayList<>(filters.size());

for (int i = 0; i < filters.size(); i++) {

GatewayFilter gatewayFilter = filters.get(i);

if (gatewayFilter instanceof Ordered) {

ordered.add(gatewayFilter);

}

else {

ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));

}

}

return ordered;

}

这里通过factory去实例化每个route的GatewayFilter

小结

spring cloud gateway的GatewayFilter主要是通过GatewayFilterFactory来生产的。而GatewayFilterFactory主要有三个抽象类:

AbstractGatewayFilterFactory

HystrixGatewayFilterFactory

ModifyRequestBodyGatewayFilterFactory

ModifyResponseBodyGatewayFilterFactory

PrefixPathGatewayFilterFactory

PreserveHostHeaderGatewayFilterFactory

RedirectToGatewayFilterFactory

RemoveRequestHeaderGatewayFilterFactory

RemoveResponseHeaderGatewayFilterFactory

RequestRateLimiterGatewayFilterFactory

RetryGatewayFilterFactory

RewritePathGatewayFilterFactory

SaveSessionGatewayFilterFactory

SecureHeadersGatewayFilterFactory

SetPathGatewayFilterFactory

SetStatusGatewayFilterFactory

StripPrefixGatewayFilterFactory

AbstractNameValueGatewayFilterFactory(继承了AbstractGatewayFilterFactory)

AddRequestHeaderGatewayFilterFactory

AddRequestParameterGatewayFilterFactory

AddResponseHeaderGatewayFilterFactory

SetRequestHeaderGatewayFilterFactory

SetResponseHeaderGatewayFilterFactory

AbstractChangeRequestUriGatewayFilterFactory

RequestHeaderToRequestUriGatewayFilterFactory

doc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值