本文主要研究一下spring cloud gateway的GatewayFilterhtml
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/GatewayFilter.javajava
/** * 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<Void>} to indicate when request processing is complete */ Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); }
如註釋所說,主要用於相似切面的非功能性需求,好比安全、超時控制等。其直接的實現類爲OrderedGatewayFilter、ModifyResponseGatewayFilter、GatewayFilterAdapterspring
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.javasegmentfault
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<Void> 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接口安全
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.javaapp
public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered { private final Config config; public ModifyResponseGatewayFilter(Config config) { this.config = config; } @Override @SuppressWarnings("unchecked") public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { ResolvableType inElementType = ResolvableType.forClass(config.getInClass()); ResolvableType outElementType = ResolvableType.forClass(config.getOutClass()); MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Optional<HttpMessageReader<?>> reader = getHttpMessageReader(codecConfigurer, inElementType, contentType); Optional<HttpMessageWriter<?>> 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<Void> 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; } }
主要用於修改responseide
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/handler/FilteringWebHandler.javaui
private static class GatewayFilterAdapter implements GatewayFilter { private final GlobalFilter delegate; public GatewayFilterAdapter(GlobalFilter delegate) { this.delegate = delegate; } @Override public Mono<Void> 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的適配器this
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.javadebug
@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(); } }
spring cloud gateway採用工廠模式來生成GatewayFilter,能夠看到這裏定義了apply方法,根據config來生成GatewayFilter。GatewayFilterFactory有幾個抽象類,分別是AbstractGatewayFilterFactory、AbstractNameValueGatewayFilterFactory(
繼承了AbstractGatewayFilterFactory
)、AbstractChangeRequestUriGatewayFilterFactory。
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java
public abstract class AbstractGatewayFilterFactory<C> extends AbstractConfigurable<C> implements GatewayFilterFactory<C> { @SuppressWarnings("unchecked") public AbstractGatewayFilterFactory() { super((Class<C>) Object.class); } public AbstractGatewayFilterFactory(Class<C> configClass) { super(configClass); } public static class NameConfig { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
它的直接實現類以下:
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractNameValueGatewayFilterFactory.java
public abstract class AbstractNameValueGatewayFilterFactory extends AbstractGatewayFilterFactory<AbstractNameValueGatewayFilterFactory.NameValueConfig> { public AbstractNameValueGatewayFilterFactory() { super(NameValueConfig.class); } public List<String> 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,其實現類以下:
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<T> extends AbstractGatewayFilterFactory<T> { private final int order; public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz, int order) { super(clazz); this.order = order; } public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz) { this(clazz, RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1); } protected abstract Optional<URI> determineRequestUri(ServerWebExchange exchange, T config); public GatewayFilter apply(T config) { return new OrderedGatewayFilter((exchange, chain) -> { Optional<URI> uri = this.determineRequestUri(exchange, config); uri.ifPresent(u -> { Map<String, Object> attributes = exchange.getAttributes(); attributes.put(GATEWAY_REQUEST_URL_ATTR, u); }); return chain.filter(exchange); }, this.order); } }
經過GATEWAY_REQUEST_URL_ATTR設置新的uri,其直接實現類爲
經過header的值來設定uri
)spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java
private List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) { List<GatewayFilter> 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<String, String> args = definition.getArgs(); if (logger.isDebugEnabled()) { logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName()); } Map<String, Object> 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<GatewayFilter> 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主要有三個抽象類: