最近有個網友問了一個問題,zuul中若是兩個filter的order同樣,是如何排序的?引發了個人興趣,特意去閱讀了它的源碼。java
若是你有使用過springcloud應該據說過zuul,它的定位是分佈式微服務中的API網關服務,固然後面可能要被gateway替代了。zuul是一個L7應用程序網關,提供了動態路由,監視,彈性,安全性等功能。zuul的大部分功能是經過filter實現的。面試
zuul定義了四種不一樣生命週期的filterspring
爲了方便操做,zuul內置了一些filter,這些filter主要經過@EnableZuulServer
和@EnableZuulProxy
註解開啓相關功能。@EnableZuulServer
註解開啓的filter功能以下:緩存
@EnableZuulProxy
註解除了開啓上面這些filter功能以外,還開啓了以下的功能:安全
只需繼承ZuulFilter
類,實現它的filterType
、filterOrder
、shouldFilter
和 run
方法便可,具體實現可參考以下代碼:springboot
public class LogFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return RequestContext.getCurrentContext().sendZuulResponse(); } @Override public Object run() throws ZuulException { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); log.info("zuul pre filter-->" + request.getRequestURL() + "-->" + request.getMethod()); return null; } }
上面的四個方法有哪些做用呢?分佈式
須要注意的是,要想使zuul的功能生效,切記要在springboot啓動類
上定義@EnableZuulServer
或@EnableZuulProxy
註解,表示開啓zuul的功能。ide
先看看全部的zuulFilter在哪裏執行的,謎底就在FilterProcessor
類的runFilters
方法中。微服務
該方法很簡單,先獲取全部zuulFilter,而後遍歷全部zuulFilter,調用processZuulFilter
方法執行具體的zuulFilter,而後將執行結果返回。學習
咱們重點看看這個方法
FilterLoader.getInstance().getFiltersByType(sType);
該方法的具體邏輯
從上面能夠看出filter的排序是經過以下方法執行的:
Collections.sort(list);
該方法底層實際上是經過list
的sort
方法實現的
看看ArrayList
的sort
方法,傳入的Comparator
爲null
它的底層又是經過Arrays
類的靜態方法sort
實現的
因爲上一步Comparator
爲null,則會執行sort
方法。
該方法是經過ComparableTimSort
類的sort
方法實現的,這個方法是最核心的方法了
咱們能夠看到該方法實際上是經過binarySort
二分查找排序的。
經過compareTo
方法比較大小。
咱們回頭再看看ZuulFilter
類
它實現了Comparable
接口,重寫了compareTo
方法
因此,看到這裏咱們能夠得出結論:ZuulFilter
是經過Integer
的compare
方法比較filterOrder
參數值大小來排序的。
咱們看看Integer
的compare
方法具體的邏輯!
若是x==y,則返回0,x<y,則返回 -1,不然返回1 前面在二分查找中,只有x<y時,纔會交換位置。
看到這裏,咱們得出這樣的結論,若是filterOrder
同樣,則Collections.sort(list);
排序時不交換位置,這按照ZuulFilter
默認加載順序。那麼,ZuulFilter的默認加載順序是怎麼樣的?
它是經過getAllFilters
方法獲取ZuulFilter
集合,該方法其實返回的是名稱爲filters
的ConcurrentHashMap
的values
,即返回Set
集合,是無序的。
因此,filterOrder切記不要定義相同的,否則可能會出現沒法預知的執行結果。
自定義排序其實有兩種方法
若是要使用Collections.sort(list);
排序,它默認用的是第一種方法,上面的filterOrder
之因此能夠排序,是由於Integer
實現了Comparable
接口,重寫了compareTo
方法
若是想本身定義排序規則能夠經過實現Comparator
接口,重寫compare
方法。
Collections.sort(list,new Comparator<Integer>(){ @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } });
它的底層也是經過二分查找實現的
zuul
中是經過filterOrder
參數的大小排序的,而在spring
中是經過@Order
註解排序的。
默認狀況下,若是不指定value值,則value是Integer的最大值。因爲排序規則是value越小,則排在越靠前,因此若是不指定value值,則它排在最後。spring
是經過OrderComparator
類排序的,它實現了Comparator
接口,它的doCompare
方法實現的排序。
最終也是調用Integer
類的compare
方法,該方法前面已經介紹過了。
若是這篇文章對您有所幫助,或者有所啓發的話,幫忙掃描下發二維碼關注一下,或者點贊、轉發、在看。在公衆號中回覆:面試、代碼神器、開發手冊、時間管理有超讚的粉絲福利,另外回覆:加羣,能夠跟不少大廠的前輩交流和學習。