/ servlet

Servlet Filter工作原理

前言

本文主要探讨Filter的链式处理结构,不会过多赘述Filter的基本功能。

Filter的链式结构

一直一来,我对多个filter如何能够实现链式处理的结构很好奇。大体说来,假若Filter A处理完后,可以将request和response交由后续的Filter B处理,这很像责任链模式(Chain of Responsibility Pattern)。但实际上它不是,而是采用类似注册查找的方式。

一个filter的核心方法为dofilter,其核心结构为:

public void doFilter(ServletRequest req, ServletResponse res,
		FilterChain chain) {
	//此处编写该filter的核心处理代码
    //...
	chain.doFilter(request, response);
}

我们怎么知道当前filter执行后,谁是接下来执行的filter呢?可以看到,filter在执行完自己的处理方法后,将request和response交给了FilterChain 的doFilter方法。FilterChain在tomcat中的具体实现类为ApplicationFilterChain,反编译后其核心代码如下:

public void doFilter(ServletRequest request, ServletResponse response) {
	// some code before
	internalDoFilter(request, response);
	// some code after
}

private void internalDoFilter(ServletRequest request,
		ServletResponse response) {
	ApplicationFilterConfig filterConfig = this.filters[(this.pos++)];
	Filter filter = null;
	filter = filterConfig.getFilter();
	filter.doFilter(request, response, this);
}

可以看到,ApplicationFilterChain的doFilter方法调用了internalDoFilter方法,internalDoFilter的功能为,从当前webcontext中注册的所有filters中得到下一个filter(通过pos变量累加来得到下一个Filter的数组位置)。然后调用该filter的doFilter方法,依次类推,周而复始及至后续的所有filter。

值得注意的是,为了保证叙述的简洁,上述源代码去除了很多,只保留了能说明问题的几句。