序
本文主要研究一下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 Monofilter(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 Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override public Mono writeWith(Publisher 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 > 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 Monofilter(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
@FunctionalInterfacepublic interface GatewayFilterFactoryextends 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 AbstractGatewayFilterFactoryextends 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 AbstractChangeRequestUriGatewayFilterFactoryextends 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 ListloadGatewayFilters(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