博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊spring cloud gateway的GatewayFilter
阅读量:6978 次
发布时间:2019-06-27

本文共 12977 字,大约阅读时间需要 43 分钟。

  hot3.png

本文主要研究一下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
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 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

@FunctionalInterfacepublic 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

转载于:https://my.oschina.net/go4it/blog/1827477

你可能感兴趣的文章
为什么很多人努力了却死一地
查看>>
开放产品开发(OPD):Archi 汉化工具下载
查看>>
VS code for python开发利器
查看>>
高性能的MySQL(1)锁和MVCC
查看>>
如何用VDP备份虚拟机
查看>>
虚拟机安装 Windows 10 9926 预览版 “准备就绪”...... 故障
查看>>
FTP服务器的防火墙通用设置规则
查看>>
遍历系统文本全文
查看>>
《人人都能看懂经济学》读书笔记
查看>>
Linux文本比较命令:diff
查看>>
Android开发实践:JNI函数签名生成器
查看>>
危机!测试工程师真的要小心了
查看>>
MySQL 高可用MMM
查看>>
Centos6.2_X86_64 _LNMP安装全程实录
查看>>
我的友情链接
查看>>
eclipse插件安装方法
查看>>
Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(1)...
查看>>
Javascript中的字符串链接和Array.join()方法时间效率对比
查看>>
内部毕业学生对老男孩教育的客观评价
查看>>
SQL Server 表和索引存储结构
查看>>