在聊Dubbo Filter
之前,我们先说说Web
标准的javax.servlet.Filter
。
public interface Filter {
// 初始化,Servlet容器启动时调用
void init(FilterConfig var1) throws ServletException;
// 做过滤动作
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
// 销毁,优雅停机才会调用
void destroy();
}
以上是javax.servlet.Filter
的接口定义。3个行为,分别是初始化,执行,销毁。
初始化和销毁动作,就不在这边聊了。看看doFilter
行为
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// do business before
filterChain.doFilter(httpRequest, response);
// do business after
return;
}
super.doFilter(httpRequest, response, filterChain);
}
实现了javax.servlet.Filter
接口的实现类,需要实现doFilter
方法。一般都会像上面这个示例一样编写代码。关键代码filterChain.doFilter(httpRequest, response);
这行代码需要开发者自己写,实际上是使用filterChain
去调用下一个filter
。FilterChain
的实例中维护了一个过滤器链的列表。每次调用doFilter
方法,就会去找下一个执行。直到最后,都执行完了就去执行servlet
。看下Tomcat
的源码实现。
// 过滤器链数组
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
// pos就是指当前要执行哪个
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
filter = filterConfig.getFilter();
// --------------------此处省略一堆代码-----------------------
filter.doFilter(request, response, this);
// --------------------此处省略一堆代码-----------------------
return;
}
// We fell off the end of the chain -- call the servlet instance
// 这边开始执行serlvet
}
从这块代码可以看到Tomcat
执行过滤器链的过程。有兴趣的朋友可以追踪下源码。把javax.servlet.Filter
放在前面说,是因为Dubbo Filter
跟javax.servlet.Filter
很像,至少对开发者来讲是这样的。
不同之处:Dubbo Filter
过滤器链的封装方式和执行方式不太一样。javax.servlet.Filter
可以很明显在ApplicationFilterChain
中知道filters
这个数组,很明显,它维护了一个过滤器链。而Dubbo Filter
是使用了Wapper
的方式。将所有的过滤器一个包着一个。看下面这张图,可能会有些感觉了。