经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
详解SpringCloud Gateway之过滤器GatewayFilter
来源:jb51  时间:2018/10/17 8:45:02  对本文有异议

在Spring-Cloud-Gateway之请求处理流程文中我们了解最终网关是将请求交给过滤器链表进行处理,接下来我们阅读Spring-Cloud-Gateway的整个过滤器类结构以及主要功能

通过源码可以看到Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,下来我依次阅读接口的主要实现功能。

GatewayFilterChain

类图


代码

  1. /**
  2.  * 网关过滤链表接口
  3.  * 用于过滤器的链式调用
  4.  * Contract to allow a {@link WebFilter} to delegate to the next in the chain.
  5.  *
  6.  * @author Rossen Stoyanchev
  7.  * @since 5.0
  8.  */
  9. public interface GatewayFilterChain {
  10.  
  11.   /**
  12.    * 链表启动调用入口方法
  13.    * Delegate to the next {@code WebFilter} in the chain.
  14.    * @param exchange the current server exchange
  15.    * @return {@code Mono<Void>} to indicate when request handling is complete
  16.    */
  17.   Mono<Void> filter(ServerWebExchange exchange);
  18.  
  19. }
  1.   /**
  2.    * 网关过滤的链表,用于过滤器的链式调用
  3.    * 过滤器链表接口的默认实现,
  4.    * 包含2个构建函数:
  5.    * 1.集合参数构建用于初始化吧构建链表
  6.    * 2. index,parent参数用于构建当前执行过滤对应的下次执行的链表 
  7.    */
  8.   private static class DefaultGatewayFilterChain implements GatewayFilterChain {
  9.  
  10.     /**
  11.      * 当前过滤执行过滤器在集合中索引
  12.      */
  13.     private final int index;
  14.     /**
  15.      * 过滤器集合
  16.      */
  17.     private final List<GatewayFilter> filters;
  18.  
  19.     public DefaultGatewayFilterChain(List<GatewayFilter> filters) {
  20.       this.filters = filters;
  21.       this.index = 0;
  22.     }
  23.  
  24.     /**
  25.      * 构建
  26.      * @param parent 上一个执行过滤器对应的FilterChain
  27.      * @param index 当前要执行过滤器的索引
  28.      */
  29.     private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
  30.       this.filters = parent.getFilters();
  31.       this.index = index;
  32.     }
  33.  
  34.     public List<GatewayFilter> getFilters() {
  35.       return filters;
  36.     }
  37.  
  38.     /**
  39.      * @param exchange the current server exchange
  40.      * @return
  41.      */
  42.     @Override
  43.     public Mono<Void> filter(ServerWebExchange exchange) {
  44.       return Mono.defer(() -> {
  45.         if (this.index < filters.size()) {
  46.           //获取当前索引的过滤器
  47.           GatewayFilter filter = filters.get(this.index);
  48.           //构建当前索引的下一个过滤器的FilterChain
  49.           DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);
  50.           //调用过滤器的filter方法执行过滤器
  51.           return filter.filter(exchange, chain);
  52.         } else {
  53.           //当前索引大于等于过滤集合大小,标识所有链表都已执行完毕,返回空
  54.           return Mono.empty(); // complete
  55.         }
  56.       });
  57.     }
  58.   }

过滤器的GatewayFilterChain 执行顺序

  1. 通过GatewayFilter集合构建顶层的GatewayFilterChain

  2. 调用顶层GatewayFilterChain,获取第一个Filter,并创建下一个Filter索引对应的GatewayFilterChain

  3. 调用filter的filter方法执行当前filter,并将下次要执行的filter对应GatewayFilterChain传入。

GatewayFilter

类图

  1. /**
  2.  * 网关路由过滤器,
  3.  * Contract for interception-style, chained processing of Web requests that may
  4.  * be used to implement cross-cutting, application-agnostic requirements such
  5.  * as security, timeouts, and others. Specific to a Gateway
  6.  *
  7.  * Copied from WebFilter
  8.  *
  9.  * @author Rossen Stoyanchev
  10.  * @since 5.0
  11.  */
  12. public interface GatewayFilter extends ShortcutConfigurable {
  13.  
  14.   String NAME_KEY = "name";
  15.   String VALUE_KEY = "value";
  16.  
  17.   /**
  18.    * 过滤器执行方法
  19.    * Process the Web request and (optionally) delegate to the next
  20.    * {@code WebFilter} through the given {@link GatewayFilterChain}.
  21.    * @param exchange the current server exchange
  22.    * @param chain provides a way to delegate to the next filter
  23.    * @return {@code Mono<Void>} to indicate when request processing is complete
  24.    */
  25.   Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
  26.  
  27. }

网关过滤器接口,有且只有一个方法filter,执行当前过滤器,并在此方法中决定过滤器链表是否继续往下执行,接下来我们看下几个主要的功能实现类

OrderedGatewayFilter

  1. /**
  2.  * 排序的网关路由过滤器,用于包装真实的网关过滤器,已达到过滤器可排序
  3.  * @author Spencer Gibb
  4.  */
  5. public class OrderedGatewayFilter implements GatewayFilter, Ordered {
  6.  
  7.   //目标过滤器
  8.   private final GatewayFilter delegate;
  9.   //排序字段
  10.   private final int order;
  11.  
  12.   public OrderedGatewayFilter(GatewayFilter delegate, int order) {
  13.     this.delegate = delegate;
  14.     this.order = order;
  15.   }
  16.  
  17.   @Override
  18.   public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  19.     return this.delegate.filter(exchange, chain);
  20.   }
  21. }

OrderedGatewayFilter实现类主要目的是为了将目标过滤器包装成可排序的对象类型。是目标过滤器的包装类

GatewayFilterAdapter

  1.   /**
  2.    * 全局过滤器的包装类,将全局路由包装成统一的网关过滤器
  3.    */
  4.   private static class GatewayFilterAdapter implements GatewayFilter {
  5.  
  6.     /**
  7.      * 全局过滤器
  8.      */
  9.     private final GlobalFilter delegate;
  10.  
  11.     public GatewayFilterAdapter(GlobalFilter delegate) {
  12.       this.delegate = delegate;
  13.     }
  14.  
  15.     @Override
  16.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  17.       return this.delegate.filter(exchange, chain);
  18.     }
  19.   }

GatewayFilterAdapter实现类主要目的是为了将GlobalFilter过滤器包装成GatewayFilter类型的对应。是GlobalFilter过滤器的包装类

GlobalFilter

GlobalFilter 为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,模式系统初始化时加载,并作用在每个路由上。

初始化加载,通过GatewayAutoConfiguration自动创建

GatewayAutoConfiguration 类

  1. /**
  2.      * 全局过滤器,用户通过HttpClient转发请求
  3.      * @param httpClient
  4.      * @param headersFilters
  5.      * @return
  6.      */
  7.     @Bean
  8.     public NettyRoutingFilter routingFilter(HttpClient httpClient,
  9.                         ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
  10.       return new NettyRoutingFilter(httpClient, headersFilters);
  11.     }
  12.  
  13.     /**
  14.      * 全局的过滤器,用户将HttpClient客户端转发请求的响应写入到原始的请求响应中
  15.      * @param properties
  16.      * @return
  17.      */
  18.     @Bean
  19.     public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) {
  20.       return new NettyWriteResponseFilter(properties.getStreamingMediaTypes());
  21.     }

GatewayLoadBalancerClientAutoConfiguration 类

  1.   /**
  2.    * 全局过滤器,用于在通过负载均衡客户端选择服务实例信息
  3.    * @param client
  4.    * @return
  5.    */
  6.   @Bean
  7.   @ConditionalOnBean(LoadBalancerClient.class)
  8.   public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {
  9.     return new LoadBalancerClientFilter(client);
  10.   }

GlobalFilter转换成GatewayFilter,并作用于每个路由上,在FilteringWebHandler实现

FilteringWebHandler类

  1.   /**
  2.    * 包装加载全局的过滤器,将全局过滤器包装成GatewayFilter
  3.    * @param filters
  4.    * @return
  5.    */
  6.   private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
  7.     return filters.stream()
  8.         .map(filter -> {
  9.           //将所有的全局过滤器包装成网关过滤器
  10.           GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
  11.           //判断全局过滤器是否实现了可排序接口
  12.           if (filter instanceof Ordered) {
  13.             int order = ((Ordered) filter).getOrder();
  14.             //包装成可排序的网关过滤器
  15.             return new OrderedGatewayFilter(gatewayFilter, order);
  16.           }
  17.           return gatewayFilter;
  18.         }).collect(Collectors.toList());
  19.   }
  20.   @Override
  21.   public Mono<Void> handle(ServerWebExchange exchange) {
  22.     //获取请求上下文设置的路由实例
  23.     Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
  24.     //获取路由定义下的网关过滤器集合
  25.     List<GatewayFilter> gatewayFilters = route.getFilters();
  26.  
  27.     //组合全局的过滤器与路由配置的过滤器
  28.     List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
  29.     //添加路由配置过滤器到集合尾部
  30.     combined.addAll(gatewayFilters);
  31.     //对过滤器进行排序
  32.     //TODO: needed or cached?
  33.     AnnotationAwareOrderComparator.sort(combined);
  34.  
  35.     logger.debug("Sorted gatewayFilterFactories: "+ combined);
  36.     //创建过滤器链表对其进行链式调用
  37.     return new DefaultGatewayFilterChain(combined).filter(exchange);
  38.   }

loadFilters方法是将全局路由使用GatewayFilterAdapter包装成GatewayFilter

handle方法

  • 获取当前请求使用的路由Route

  • 获取路由配置的过滤器集合route.getFilters()

  • 合并全过滤器与路由配置过滤器combined

  • 对过滤器排序AnnotationAwareOrderComparator.sort

  • 通过过滤器集合构建顶级链表DefaultGatewayFilterChain,并对其当前请求调用链表的filter方法。

==备注==:

Spring-Cloud-Gateway的过滤器接口分为两种:

  • GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器

  • GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上

至此,网关过滤器的整个结构以及加载使用流程源码已经阅读完毕,下篇重点学习下路由配置的过滤器加载创建流程

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号