最近有个网友问了一个问题,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
方法,该方法前面已经介绍过了。
若是这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,或者点赞、转发、在看。在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,能够跟不少大厂的前辈交流和学习。