在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://www.jianshu.com/p/eb3a67291050