责任链模式是一种对象的行为模式。在责任链模式里,不少对象由每个对象对其下家的引用而链接起来造成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪个对象最终处理这个请求,这使得系统能够在不影响客户端的状况下动态地从新组织和分配责任。java
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不容许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的状况。web
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求能够最终不被任何接收端对象所接收。数组
纯的责任链模式的实际例子很难找到,通常看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。可是在实际的系统里,纯的责任链很难找到。若是坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。app
众所周知Tomcat中的Filter就是使用了责任链模式,建立一个Filter除了要在web.xml文件中作相应配置外,还须要实现javax.servlet.Filter接口。this
public class TestFilter implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } }
使用DEBUG模式所看到的结果以下spa
其实在真正执行到TestFilter类以前,会通过不少Tomcat内部的类。顺带提一下其实Tomcat的容器设置也是责任链模式,注意被红色方框所圈中的类,从Engine到Host再到Context一直到Wrapper都是经过一个链传递请求。被绿色方框所圈中的地方有一个名为ApplicationFilterChain的类,ApplicationFilterChain类所扮演的就是抽象处理者角色,而具体处理者角色由各个Filter扮演。code
第一个疑问是ApplicationFilterChain将全部的Filter存放在哪里?xml
答案是保存在ApplicationFilterChain类中的一个ApplicationFilterConfig对象的数组中。对象
那ApplicationFilterConfig对象又是什么呢?blog
ApplicationFilterConfig是一个Filter容器。
当一个web应用首次启动时ApplicationFilterConfig会自动实例化,它会从该web应用的web.xml文件中读取配置的Filter的信息,而后装进该容器。
刚刚看到在ApplicationFilterChain类中所建立的ApplicationFilterConfig数组长度为零,那它是在何时被从新赋值的呢?
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
是在调用ApplicationFilterChain类的addFilter()方法时。
变量n用来记录当前过滤器链里面拥有的过滤器数目,默认状况下n等于0,ApplicationFilterConfig对象数组的长度也等于0,因此当第一次调用addFilter()方法时,if (n == filters.length)的条件成立,ApplicationFilterConfig数组长度被改变。以后filters[n++] = filterConfig;将变量filterConfig放入ApplicationFilterConfig数组中并将当前过滤器链里面拥有的过滤器数目+1。
那ApplicationFilterChain的addFilter()方法又是在什么地方被调用的呢?
是在ApplicationFilterFactory类的createFilterChain()方法中。
能够将如上代码分为两段,51行以前为第一段,51行以后为第二段。
第一段的主要目的是建立ApplicationFilterChain对象以及一些参数设置。
第二段的主要目的是从上下文中获取全部Filter信息,以后使用for循环遍历并调用filterChain.addFilter(filterConfig);将filterConfig放入ApplicationFilterChain对象的ApplicationFilterConfig数组中。
那ApplicationFilterFactory类的createFilterChain()方法又是在什么地方被调用的呢?
是在StandardWrapperValue类的invoke()方法中被调用的。
那正常的流程应该是这样的:
在StandardWrapperValue类的invoke()方法中调用ApplicationFilterChai类的createFilterChain()方法———>在ApplicationFilterChai类的createFilterChain()方法中调用ApplicationFilterChain类的addFilter()方法———>在ApplicationFilterChain类的addFilter()方法中给ApplicationFilterConfig数组赋值。
根据上面的代码能够看出StandardWrapperValue类的invoke()方法在执行完createFilterChain()方法后,会继续执行ApplicationFilterChain类的doFilter()方法,而后在doFilter()方法中会调用internalDoFilter()方法。
这里的filter.doFilter(request, response, this);就是调用咱们前面建立的TestFilter中的doFilter()方法。而TestFilter中的doFilter()方法会继续调用chain.doFilter(request, response);方法,而这个chain其实就是ApplicationFilterChain,因此调用过程又回到了上面调用dofilter和调用internalDoFilter方法,这样执行直到里面的过滤器所有执行。
因为invoke()方法较长,因此将不少地方省略。