您的位置:首页 > 其它

Filter过滤器机制

2017-01-18 18:02 155 查看
tomcat内部过滤器采用了责任链的设计模式,

Tomcat的过滤器主要由Filter、FilterChain组成,FilterChain包含一个Filter数组.当Wrapper执行FilterChain的doFilter(request,response)方法时,FilterChain首先调用第一个Filter的doFilter(request,response,filterchain)方法,当第一个filter做完过滤操作后,它又会调用filterchain的doFilter方法,此时filterchain的当前filter已变为第二个filter,第二个filter又执行dofilter方法,依此类推,直至所有过滤器都执行完毕。

public interface Filter {

.....

//执行过滤

public void doFilter ( ServletRequest request, ServletResponse response, throws IOException, ServletException;

}

public interface FilterChain {

public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;

}

FilterConfig接口检索过滤器名、初始化参数以及活动的Servlet上下文。ApplicationFilterConfig是其实现类

ApplicationFilterChain在catalina.jar的org.apache.catalina.core包中

class ApplicationFilterChain implements FilterChain {

..................

private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];

private int pos = 0;
private int n = 0;

//pos为当前filter的所在位置,n为filters数组的长度

if (pos < n) {

//pos++执行后,把filterchain的当前filter指向下一个

ApplicationFilterConfig filterConfig = filters[pos++];

Filter filter = null;

try {

filter = filterConfig.getFilter();

//filter执行过滤操作

filter.doFilter(request, response, this);

}

...

}

}

实例如下:

class SampleFilter implements Filter {

........

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)

throws IOException, ServletException {

//do something

.....

//request, response传递给下一个过滤器进行过滤

chain.doFilter(request, response);

}

}

先描述tomcat的方法调用序列。


具体过程如下:

(1)connector 创建 request 和 response 对象;

(2)connector 调用 StandardContext 实例的 invoke 方法;

(3)StandardContext 接着调用其 pipeline 的 invoke 方法,StandardContext 中 pipeline 的 basic valve 是

StandardContextValve,因此,StandardContext 的 pipeline 会调用 StandardContextValve 的 invoke 方法;

(4)StandardContextValve 的 invoke 方法获取 wrapper 处理请求,调用 wrapper 的 invoke 方法;

(5)StandardWrapper 是 Wrapper 接口的标准实现,StandardWrapper 实例的 invoke 方法会调用其

pipeline 的 invoke 方法;

(6)StandardWrapper 的 pipeline 中的 basic valve 是 StandardWrapperValve,因此,会调用其 invoke 方

法,StandardWrapperValve 调用 wrapper 的 allocate 方法获取 servlet 实例;

(7)allocate 方法调用 load 方法载入 servlet 类,若已经载入,则无需重复载入;

(8)load 方法调用 servlet 的 init 方法;

(9)StandardWrapperValve 调用 servlet 的 service 方法。

StandardWrapperValve中的主要代码如下:

ApplicationFilterChain filterChain =

createFilterChain(request, servlet);

/*略

String jspFile = wrapper.getJspFile();

if (jspFile != null)

sreq.setAttribute(Globals.JSP_FILE_ATTR, jspFile);

else

sreq.removeAttribute(Globals.JSP_FILE_ATTR);

if ((servlet != null) && (filterChain != null)) {

filterChain.doFilter(sreq, sres);

}

sreq.removeAttribute(Globals.JSP_FILE_ATTR);

在StandardWrapperValve的invoke中(也就是上面贴的代码),第10行的代码就是调用servlet的入口,传说中的doFilter()。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: