好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

详解SpringCloud Gateway之过滤器GatewayFilter

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

通过源码可以看到spring-cloud-gateway的filter包中吉接口有如下三个,gatewayfilter,globalfilter,gatewayfilterchain,下来我依次阅读接口的主要实现功能。

gatewayfilterchain

类图

代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/**

  * 网关过滤链表接口

  * 用于过滤器的链式调用

  * contract to allow a {@link webfilter} to delegate to the next in the chain.

  *

  * @author rossen stoyanchev

  * @since 5.0

  */

public interface gatewayfilterchain {

 

   /**

    * 链表启动调用入口方法

    * delegate to the next {@code webfilter} in the chain.

    * @param exchange the current server exchange

    * @return {@code mono<void>} to indicate when request handling is complete

    */

   mono< void > filter(serverwebexchange exchange);

 

}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

/**

  * 网关过滤的链表,用于过滤器的链式调用

  * 过滤器链表接口的默认实现,

  * 包含2个构建函数:

  * 1.集合参数构建用于初始化吧构建链表

  * 2. index,parent参数用于构建当前执行过滤对应的下次执行的链表

  */

private static class defaultgatewayfilterchain implements gatewayfilterchain {

 

   /**

    * 当前过滤执行过滤器在集合中索引

    */

   private final int index;

   /**

    * 过滤器集合

    */

   private final list<gatewayfilter> filters;

 

   public defaultgatewayfilterchain(list<gatewayfilter> filters) {

     this .filters = filters;

     this .index = 0 ;

   }

 

   /**

    * 构建

    * @param parent 上一个执行过滤器对应的filterchain

    * @param index 当前要执行过滤器的索引

    */

   private defaultgatewayfilterchain(defaultgatewayfilterchain parent, int index) {

     this .filters = parent.getfilters();

     this .index = index;

   }

 

   public list<gatewayfilter> getfilters() {

     return filters;

   }

 

   /**

    * @param exchange the current server exchange

    * @return

    */

   @override

   public mono< void > filter(serverwebexchange exchange) {

     return mono.defer(() -> {

       if ( this .index < filters.size()) {

         //获取当前索引的过滤器

         gatewayfilter filter = filters.get( this .index);

         //构建当前索引的下一个过滤器的filterchain

         defaultgatewayfilterchain chain = new defaultgatewayfilterchain( this , this .index + 1 );

         //调用过滤器的filter方法执行过滤器

         return filter.filter(exchange, chain);

       } else {

         //当前索引大于等于过滤集合大小,标识所有链表都已执行完毕,返回空

         return mono.empty(); // complete

       }

     });

   }

}

过滤器的gatewayfilterchain 执行顺序

通过gatewayfilter集合构建顶层的gatewayfilterchain 调用顶层gatewayfilterchain,获取第一个filter,并创建下一个filter索引对应的gatewayfilterchain 调用filter的filter方法执行当前filter,并将下次要执行的filter对应gatewayfilterchain传入。

gatewayfilter

类图

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

/**

  * 网关路由过滤器,

  * 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);

 

}

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

orderedgatewayfilter

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

/**

  * 排序的网关路由过滤器,用于包装真实的网关过滤器,已达到过滤器可排序

  * @author spencer gibb

  */

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;

   }

 

   @override

   public mono< void > filter(serverwebexchange exchange, gatewayfilterchain chain) {

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

   }

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

gatewayfilteradapter

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/**

  * 全局过滤器的包装类,将全局路由包装成统一的网关过滤器

  */

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);

   }

}

gatewayfilteradapter实现类主要目的是为了将globalfilter过滤器包装成gatewayfilter类型的对应。是globalfilter过滤器的包装类

globalfilter

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

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

gatewayautoconfiguration 类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

/**

  * 全局过滤器,用户通过httpclient转发请求

  * @param httpclient

  * @param headersfilters

  * @return

  */

@bean

public nettyroutingfilter routingfilter(httpclient httpclient,

                     objectprovider<list<httpheadersfilter>> headersfilters) {

   return new nettyroutingfilter(httpclient, headersfilters);

}

 

/**

  * 全局的过滤器,用户将httpclient客户端转发请求的响应写入到原始的请求响应中

  * @param properties

  * @return

  */

@bean

public nettywriteresponsefilter nettywriteresponsefilter(gatewayproperties properties) {

   return new nettywriteresponsefilter(properties.getstreamingmediatypes());

}

gatewayloadbalancerclientautoconfiguration 类

?

1

2

3

4

5

6

7

8

9

10

/**

  * 全局过滤器,用于在通过负载均衡客户端选择服务实例信息

  * @param client

  * @return

  */

@bean

@conditionalonbean (loadbalancerclient. class )

public loadbalancerclientfilter loadbalancerclientfilter(loadbalancerclient client) {

   return new loadbalancerclientfilter(client);

}

globalfilter转换成gatewayfilter,并作用于每个路由上,在filteringwebhandler实现

filteringwebhandler类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

/**

  * 包装加载全局的过滤器,将全局过滤器包装成gatewayfilter

  * @param filters

  * @return

  */

private static list<gatewayfilter> loadfilters(list<globalfilter> filters) {

   return filters.stream()

       .map(filter -> {

         //将所有的全局过滤器包装成网关过滤器

         gatewayfilteradapter gatewayfilter = new gatewayfilteradapter(filter);

         //判断全局过滤器是否实现了可排序接口

         if (filter instanceof ordered) {

           int order = ((ordered) filter).getorder();

           //包装成可排序的网关过滤器

           return new orderedgatewayfilter(gatewayfilter, order);

         }

         return gatewayfilter;

       }).collect(collectors.tolist());

}

@override

public mono< void > handle(serverwebexchange exchange) {

   //获取请求上下文设置的路由实例

   route route = exchange.getrequiredattribute(gateway_route_attr);

   //获取路由定义下的网关过滤器集合

   list<gatewayfilter> gatewayfilters = route.getfilters();

 

   //组合全局的过滤器与路由配置的过滤器

   list<gatewayfilter> combined = new arraylist<>( this .globalfilters);

   //添加路由配置过滤器到集合尾部

   combined.addall(gatewayfilters);

   //对过滤器进行排序

   //todo: needed or cached?

   annotationawareordercomparator.sort(combined);

 

   logger.debug( "sorted gatewayfilterfactories: " + combined);

   //创建过滤器链表对其进行链式调用

   return new defaultgatewayfilterchain(combined).filter(exchange);

}

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配置在全局,作用在所有路由上

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

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

原文链接:https://HdhCmsTestjianshu测试数据/p/eb3a67291050

查看更多关于详解SpringCloud Gateway之过滤器GatewayFilter的详细内容...

  阅读:12次