Tomcat
的类ApplicationFilterChain
是一个Java Servlet API
规范javax.servlet.FilterChain
的实现,用于管理某个请求request
的一组过滤器Filter
的执行。当针对一个request
所定义的一组过滤器Filter
处理完该请求后,组后一个doFilter()
调用才会执行目标Servlet
的方法service()
,然后响应对象response
会按照相反的顺序依次被这些Filter
处理,最终到达客户端。
事实上,一个Filter
的逻辑可以被设计成既可以在目标servlet
执行前执行,也可以在目标servlet
执行之后执行,或者二者都有,甚至可以不执行目标servlet
而是自己直接响应客户端。因此,在一个ApplicationFilterChain
链执行到目标servlet
实例的service()
方法时,你可以认为此时所有Filter
被设计在servlet
执行之前执行的逻辑都执行完了,而所有Filter
的被设计在servlet
执行之后执行的逻辑都还尚未执行。
/*
* 此源代码摘自Tomcat版本 8.5.23
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
* Implementation of javax.servlet.FilterChain used to manage
* the execution of a set of filters for a particular request. When the
* set of defined filters has all been executed, the next call to
* doFilter() will execute the servlet's service()
* method itself.
*
* @author Craig R. McClanahan
*/
public final class ApplicationFilterChain implements FilterChain {
// Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
static {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest = new ThreadLocal<>();
lastServicedResponse = new ThreadLocal<>();
} else {
lastServicedRequest = null;
lastServicedResponse = null;
}
}
// -------------------------------------------------------------- Constants
public static final int INCREMENT = 10;
// ----------------------------------------------------- Instance Variables
/**
* Filters. 执行目标Servlet.service()方法前需要经历的过滤器Filter,初始化为0个元素的数组对象
*/
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
/**
* The int which is used to maintain the current position
* in the filter chain.
* 用于记录过滤器链中当前所执行的过滤器的位置,是当前过滤器在filters数组的下标,初始化为0
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
* 过滤器链中过滤器的个数(注意:并不是数组filters的长度),初始化为0,和filters数组的初始长度一致
*/
private int n = 0;
/**
* The servlet instance to be executed by this chain.
* 该过滤器链执行完过滤器后最终要执行的目标Servlet
*/
private Servlet servlet = null;
/**
* Does the associated servlet instance support async processing?
* 所关联的Servlet实例是否支持异步处理 ? 缺省为 false,表示缺省情况下不支持异步处理。
*/
private boolean servletSupportsAsync = false;
/**
* The string manager for our package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Static class array used when the SecurityManager is turned on and
* doFilter
is invoked.
*/
private static final Class<?>[] classType = new Class[]{
ServletRequest.class, ServletResponse.class, FilterChain.class};
/**
* Static class array used when the SecurityManager is turned on and
* service
is invoked.
*/
private static final Class<?>[] classTypeUsedInService = new Class[]{
ServletRequest.class, ServletResponse.class};
// ---------------------------------------------------- FilterChain Methods
/**
* Invoke the next filter in this chain, passing the specified request
* and response. If there are no more filters in this chain, invoke
* the service() method of the servlet itself.
* 执行过滤器链中的下一个过滤器Filter。如果链中所有过滤器都执行过,
* 则调用servlet的service()方法。
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// 下面的if-else分支主要是根据Globals.IS_SECURITY_ENABLED是true还是false决定
// 如何调用目标逻辑,但两种情况下,目标逻辑最终都是 internalDoFilter(req,res)
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
// 找到目标 Filter 对象
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
// 执行目标 Filter 对象的 doFilter方法,
// 注意,这里当前ApplicationFilterChain对象被传递到了目标
// Filter对象的doFilter方法,而目标Filter对象的doFilter在执行完自己
// 被指定的逻辑之后会反过来调用这个ApplicationFilterChain对象的
// doFilter方法,只是pos向前推进了一个过滤器。这个ApplicationFilterChain
// 和Filter之间反复调用彼此doFilter方法的过程一直持续直到当前链发现所有的
// Filter都已经被执行
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
// 这里是过滤器链中所有的过滤器都已经被执行的情况,现在需要调用servlet实例本身了。
// !!! 注意 : 虽然这里开始调用servlet实例了,但是从当前方法执行堆栈可以看出,过滤器链
// 和链中过滤器的doFilter方法的执行帧还在堆栈中并未退出,他们会在servlet实例的逻辑
// 执行完后,分别执行完自己剩余的的逻辑才会逐一结束。
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
/**
* The last request passed to a servlet for servicing from the current
* thread.
*
* @return The last request to be serviced.
*/
public static ServletRequest getLastServicedRequest() {
return lastServicedRequest.get();
}
/**
* The last response passed to a servlet for servicing from the current
* thread.
*
* @return The last response to be serviced.
*/
public static ServletResponse getLastServicedResponse() {
return lastServicedResponse.get();
}
// -------------------------------------------------------- Package Methods
/**
* Add a filter to the set of filters that will be executed in this chain.
* 往当前要执行的过滤器链的过滤器集合filters中增加一个过滤器
* @param filterConfig The FilterConfig for the servlet to be executed
*/
void addFilter(ApplicationFilterConfig filterConfig) {
// Prevent the same filter being added multiple times
// 去重处理,如果已经添加进来则避免二次添加
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
if (n == filters.length) {
// !!! 请注意:每次需要扩容时并不是增加一个元素空间,而是增加INCREMENT个,
// 这个行为的结果是filters数组的长度和数组中过滤器的个数n并不相等
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
/**
* Release references to the filters and wrapper executed by this chain.
*/
void release() {
for (int i = 0; i < n; i++) {
filters[i] = null;
}
n = 0;
pos = 0;
servlet = null;
servletSupportsAsync = false;
}
/**
* Prepare for reuse of the filters and wrapper executed by this chain.
*/
void reuse() {
pos = 0;
}
/**
* Set the servlet that will be executed at the end of this chain.
*
* @param servlet The Wrapper for the servlet to be executed
*/
void setServlet(Servlet servlet) {
this.servlet = servlet;
}
void setServletSupportsAsync(boolean servletSupportsAsync) {
this.servletSupportsAsync = servletSupportsAsync;
}
/**
* Identifies the Filters, if any, in this FilterChain that do not support
* async.
*
* @param result The Set to which the fully qualified class names of each
* Filter in this FilterChain that does not support async will
* be added
*/
public void findNonAsyncFilters(Set<String> result) {
for (int i = 0; i < n ; i++) {
ApplicationFilterConfig filter = filters[i];
if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) {
result.add(filter.getFilterClass());
}
}
}
}