Tomcat流程

StandardWrapperValue

StandardWrapperValue是Wrapper的标准阀,用在Pipleline流程中的最后一个valve执行。当Request请求到达Context的时候,继续传递给Wrapper,首先是调用StandardWrapper的Invoke方法(ContainerBase父类中),如下.

public void invoke(Request request, Response response)
        throws IOException, ServletException {
        pipeline.invoke(request, response);
    }

pipeline就是与容器关联的一系列处理流程,StandardWrapperValve在初始化的时候就被加入到了pipeline中。而下面调用的pipeline的invoke方法,就是调用里面的各种Valve的invoke方法。

package tomcat.p4.core;
 
import java.util.Map;
 
import tomcat.p4.Pipline;
import tomcat.p4.PiplineContext;
import tomcat.p4.Valve;
 
/**
 * 一个基本的pipline实现
 * @author zhoufeng
 */
public class SimplePipline implements Pipline{
    
    /**
     * 阀门列表(相当于一系列的Filter)
     */
    private Valve[] valves = new Valve[0];
    
    /**
     * 最终要执行的内容
     */
    private Valve basic ;
 
    
    @Override
    public void setBasic(Valve basic) {
        this.basic = basic ;
    }
 
    /**
     * 添加一个阀
     */
    @Override
    public void addValve(Valve valve) {
        Valve[] newValves = new Valve[valves.length + 1];
        System.arraycopy(valves, 0, newValves, 0, valves.length); 
        newValves[newValves.length - 1] = valve ;
        valves = newValves ;
    }
 
    /**
     * 执行管道中的内容(注意这里使用内部类实例SimplePiplineContext实现)
     */
    @Override
    public void invoke(Map<String, Object> params) {
        new SimplePiplineContext().invokeNext(params); 
    }
    
    /**
     * 这里使用一个私有的内部类实现PiplineContext,用于线性的依次执行pipline中的valves,然后执行basic
     * @author zhoufeng
     *
     */
    private class SimplePiplineContext implements PiplineContext{
        
        /**
         * 记录当前正在执行到哪个valve
         */
        private int step = 0 ;
 
        @Override
        public void invokeNext(Map<String, Object> params) {
            int curStep = step ;    
            step++;
            if(curStep < valves.length){
                valves[curStep].invoke(params , this); 
            }else if(curStep == valves.length){
                if(SimplePipline.this.basic != null){
                    SimplePipline.this.basic.invoke(params, this); 
                }
            }else{
                throw new RuntimeException("no valve fond");
            }
        }
        
    }
 
    
}

下面就是StandedWrapperValve的核心逻辑,invoke方法:

public void invoke(Request request, Response response,
                       ValveContext valveContext)
        throws IOException, ServletException {
        // Initialize local variables we may need
        boolean unavailable = false;
        Throwable throwable = null;
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        ServletRequest sreq = request.getRequest();
        ServletResponse sres = response.getResponse();
        Servlet servlet = null;
        HttpServletRequest hreq = null;
        if (sreq instanceof HttpServletRequest)
            hreq = (HttpServletRequest) sreq;
        HttpServletResponse hres = null;
        if (sres instanceof HttpServletResponse)
            hres = (HttpServletResponse) sres;

        // Check for the application being marked unavailable
        if (!((Context) wrapper.getParent()).getAvailable()) {
            //503
            hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                           sm.getString("standardContext.isUnavailable"));
            unavailable = true;
        }

        // Check for the servlet being marked unavailable
        if (!unavailable && wrapper.isUnavailable()) {
            log(sm.getString("standardWrapper.isUnavailable",
                             wrapper.getName()));
            if (hres == null) {
                ;       // NOTE - Not much we can do generically
            } else {
                long available = wrapper.getAvailable();
                if ((available > 0L) && (available < Long.MAX_VALUE))
                    hres.setDateHeader("Retry-After", available);
                hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                               sm.getString("standardWrapper.isUnavailable",
                                            wrapper.getName()));
            }
            unavailable = true;
        }

        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                //通过Wrapper获取Servlet实例,内部已经调用了service(request, response)方法,对req与res进行了字段赋值
                //下面是对Response和Request进行后续的处理
                servlet = wrapper.allocate();
            }
        } catch (ServletException e) {
            log(sm.getString("standardWrapper.allocateException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        } catch (Throwable e) {
            log(sm.getString("standardWrapper.allocateException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }

        // Acknowlege the request
        try {
            response.sendAcknowledgement();
        } catch (IOException e) {
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
            log(sm.getString("standardWrapper.acknowledgeException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            log(sm.getString("standardWrapper.acknowledgeException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }

        // Create the filter chain for this request
        // 创建对于Request与Response的过滤链
        ApplicationFilterChain filterChain =
            createFilterChain(request, servlet);

        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        try {
            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)) {
                //使用过滤链过滤Request与Response
                filterChain.doFilter(sreq, sres);
            }
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
        } catch (IOException e) {
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
            log(sm.getString("standardWrapper.serviceException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (UnavailableException e) {
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
            log(sm.getString("standardWrapper.serviceException",
                             wrapper.getName()), e);
            wrapper.unavailable(e);
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE))
                hres.setDateHeader("Retry-After", available);
            hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                           sm.getString("standardWrapper.isUnavailable",
                                        wrapper.getName()));
            // Do not save exception in 'throwable', because we
            // do not want to do exception(request, response, e) processing
        } catch (ServletException e) {
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
            log(sm.getString("standardWrapper.serviceException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            sreq.removeAttribute(Globals.JSP_FILE_ATTR);
            log(sm.getString("standardWrapper.serviceException",
                             wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
        }

        // Release the filter chain (if any) for this request
        try {
            if (filterChain != null)
                //释放过滤链
                filterChain.release();
        } catch (Throwable e) {
            log(sm.getString("standardWrapper.releaseFilters",
                             wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }

        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                //释放servlet
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            log(sm.getString("standardWrapper.deallocateException",
                             wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }

        // If this servlet has been marked permanently unavailable,
        // unload it and release this instance
        try {
            if ((servlet != null) &&
                (wrapper.getAvailable() == Long.MAX_VALUE)) {
                //回收所有的Servlet
                wrapper.unload();
            }
        } catch (Throwable e) {
            log(sm.getString("standardWrapper.unloadException",
                             wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }

    }

StandardWrapper 的 allocate 方法 -- 实例化Servlet

public Servlet allocate() throws ServletException {

    if (debug >= 1)
        log("Allocating an instance");

    // If we are currently unloading this servlet, throw an exception
    if (unloading)
        throw new ServletException
        (sm.getString("standardWrapper.unloading", getName()));

    // If not SingleThreadedModel, return the same instance every time
    if (!singleThreadModel) {

        // Load and initialize our instance if necessary
        if (instance == null) {
            synchronized (this) {
                if (instance == null) {
                    try {
                        //加载Servlet
                        instance = loadServlet();
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                }
            }
        }
        //如果不是 SingleThreadModel 只会存在一个实例,所以直接返回唯一的实例就行
        //SingleThreadModel 表示同一个对象在同一时刻只能被一个线程访问,所以会创建多个对象来处理多线程。这里会用对象池来管理对象
        if (!singleThreadModel) {
            if (debug >= 2)
                log("  Returning non-STM instance");
            countAllocated++;
            return (instance);
        }

    }

    synchronized (instancePool) {
        //活动数量大于实例数量,要一直创建新的 Servlet 对象
        //注意这个活动数量不是 Servlet 的数量,应该是活动线程的数量
        while (countAllocated >= nInstances) {
            // Allocate a new instance if possible, or else wait
            if (nInstances < maxInstances) {
                //如果实例数量小于最大实例数量,创建新的 Servlet 对象
                //注意这里最大数量默认 20
                try {
                    instancePool.push(loadServlet());
                    nInstances++;
                } catch (ServletException e) {
                    throw e;
                } catch (Throwable e) {
                    throw new ServletException
                        (sm.getString("standardWrapper.allocate"), e);
                }
            } else {
                //如果实例数量达到最大数量,等待其它 Servlet 结束
                try {
                    instancePool.wait();
                } catch (InterruptedException e) {
                    ;
                }
            }
        }
        if (debug >= 2)
            log("  Returning allocated STM instance");
        //如果活动线程数量小于实例数量,表示有空闲的 Servlet 对象来处理活动线程
        //这里直接返回空闲的 Servlet 对象
        countAllocated++;
        return (Servlet) instancePool.pop();

    }

}

StandardWrapper 的 loadServlet 方法

public synchronized Servlet loadServlet() throws ServletException {

    // Nothing to do if we already have an instance or an instance pool
    if (!singleThreadModel && (instance != null))
        return instance;

    PrintStream out = System.out;
    SystemLogHandler.startCapture();
    Servlet servlet = null;
    try {
        // If this "servlet" is really a JSP file, get the right class.
        // HOLD YOUR NOSE - this is a kludge that avoids having to do special
        // case Catalina-specific code in Jasper - it also requires that the
        // servlet path be replaced by the <jsp-file> element content in
        // order to be completely effective
        //获取servlet类的全路径
        String actualClass = servletClass;
        if ((actualClass == null) && (jspFile != null)) {
            Wrapper jspWrapper = (Wrapper)
                ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
            if (jspWrapper != null)
                actualClass = jspWrapper.getServletClass();
        }

        // Complain if no servlet class has been specified
        if (actualClass == null) {
            unavailable(null);
            throw new ServletException
                (sm.getString("standardWrapper.notClass", getName()));
        }

        // Acquire an instance of the class loader to be used
        //获取加载器
        Loader loader = getLoader();
        if (loader == null) {
            unavailable(null);
            throw new ServletException
                (sm.getString("standardWrapper.missingLoader", getName()));
        }
        //获取类加载器
        ClassLoader classLoader = loader.getClassLoader();

        // Special case class loader for a container provided servlet
        if (isContainerProvidedServlet(actualClass)) {
            classLoader = this.getClass().getClassLoader();
            log(sm.getString
                ("standardWrapper.containerServlet", getName()));
        }

        // Load the specified servlet class from the appropriate class loader
        Class classClass = null;
        try {
            //加载 Servlet 对象的类到jvm
            if (classLoader != null) {
                System.out.println("Using classLoader.loadClass");
                classClass = classLoader.loadClass(actualClass);
            } else {
                System.out.println("Using forName");
                classClass = Class.forName(actualClass);
            }
        } catch (ClassNotFoundException e) {
            unavailable(null);
            throw new ServletException
                (sm.getString("standardWrapper.missingClass", actualClass),
                 e);
        }
        if (classClass == null) {
            unavailable(null);
            throw new ServletException
                (sm.getString("standardWrapper.missingClass", actualClass));
        }

        // Instantiate and initialize an instance of the servlet class itself
        try {
            //通过反射实例化 Servlet 对象
            servlet = (Servlet) classClass.newInstance();
        } catch (ClassCastException e) {
            unavailable(null);
            // Restore the context ClassLoader
            throw new ServletException
                (sm.getString("standardWrapper.notServlet", actualClass), e);
        } catch (Throwable e) {
            unavailable(null);
            // Restore the context ClassLoader
            throw new ServletException
                (sm.getString("standardWrapper.instantiate", actualClass), e);
        }

        // Check if loading the servlet in this web application should be
        // allowed
        if (!isServletAllowed(servlet)) {
            throw new SecurityException
                (sm.getString("standardWrapper.privilegedServlet",
                              actualClass));
        }

        // Special handling for ContainerServlet instances
        if ((servlet instanceof ContainerServlet) &&
            isContainerProvidedServlet(actualClass)) {
            System.out.println("calling setWrapper");                  
            ((ContainerServlet) servlet).setWrapper(this);
            System.out.println("after calling setWrapper");                  
        }


        // Call the initialization method of this servlet
        try {
            //发送事件
            instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
                                              servlet);
            //调用 Servlet 的init方法
            servlet.init(facade);
            // Invoke jspInit on JSP pages
            if ((loadOnStartup > 0) && (jspFile != null)) {
                // Invoking jspInit
                HttpRequestBase req = new HttpRequestBase();
                HttpResponseBase res = new HttpResponseBase();
                req.setServletPath(jspFile);
                req.setQueryString("jsp_precompile=true");
                servlet.service(req, res);
            }
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet);
        } catch (UnavailableException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw f;
        } catch (Throwable f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw new ServletException
                (sm.getString("standardWrapper.initException", getName()), f);
        }

        // Register our newly initialized instance
        //如果当前 Servlet 实现了 SingleThreadModel 接口,加入对象池中
        singleThreadModel = servlet instanceof SingleThreadModel;
        if (singleThreadModel) {
            if (instancePool == null)
                instancePool = new Stack();
        }
        fireContainerEvent("load", this);
    } finally {
        String log = SystemLogHandler.stopCapture();
        if (log != null && log.length() > 0) {
            if (getServletContext() != null) {
                getServletContext().log(log);
            } else {
                out.println(log);
            }
        }
    }
    //返回创建的 Servlet 对象
    return servlet;
}

StandedWrapperValve 的 createFilterChain方法

private ApplicationFilterChain createFilterChain(Request request,
                                                     Servlet servlet) {

        if (servlet == null)
            return (null);

        // 创建并且初始化一个过滤链对象ApplicationFilterChain
        ApplicationFilterChain filterChain = new ApplicationFilterChain();
        filterChain.setServlet(servlet);

        StandardWrapper wrapper = (StandardWrapper) getContainer();
        filterChain.setSupport(wrapper.getInstanceSupport());

        // 获取Context的过滤mappings
        StandardContext context = (StandardContext) wrapper.getParent();
        FilterMap filterMaps[] = context.findFilterMaps();

        if ((filterMaps == null) || (filterMaps.length == 0))
            return (filterChain);

        // 获取我们需要的匹配 fliter mappings 的信息
        String requestPath = null;
        if (request instanceof HttpRequest) {
            HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
            String contextPath = hreq.getContextPath(); //设置的一个context对用的mapper匹配路径
            if (contextPath == null) {
                contextPath = "";
            }
            String requestURI = ((HttpRequest) request).getDecodedRequestURI();
            //去掉RequestURI中的contextPath
            if (requestURI.length() >= contextPath.length()) {
                requestPath = requestURI.substring(contextPath.length());
            }
        }

        String servletName = wrapper.getName();
        int n = 0;

        // 根据RequestURI匹配FilterMaps中的过滤项,添加到filterChain中
        for (int i = 0; i < filterMaps.length; i++) {
            if (!matchFiltersURL(filterMaps[i], requestPath))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                continue;
            }
            filterChain.addFilter(filterConfig);
            n++;
        }

        // 根据StanderWrapper的Name来匹配FilterMaps中的过滤项,添加到filterChain
        for (int i = 0; i < filterMaps.length; i++) {
            if (!matchFiltersServlet(filterMaps[i], servletName))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                continue;
            }
            filterChain.addFilter(filterConfig);
            n++;
        }

        return (filterChain);
    }
使用过滤链过滤Request与Response:filterChain.doFilter(sreq, sres);

这里是调用ApplicationFilterChain的doFilter()方法,doFilter内部有调用了 internalDoFilter()方法。下面是internalDoFilter方法的实现:



作者:mecury
链接:https://www.jianshu.com/p/e6a98cab6b72
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

/*
 * 此源代码摘自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
     * <code>doFilter</code> 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
     * <code>service</code> 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());
            }
        }
    }
}

释放servlet,释放的STM类型的servlet会被放入的stack中,以后会被再次使用:deallocate(Servlet servlet)
public void deallocate(Servlet servlet) throws ServletException {

        //如果不是STM,就直接返回。STM类型的Servlet每次只有一个Servelt在执行Service方法
        if (!singleThreadModel) {
            countAllocated--;
            return;
        }

        // 如果是STM,就放入到实例池中,以备后来使用
        synchronized (instancePool) {
            countAllocated--;
            instancePool.push(servlet);
            instancePool.notify();
        }
    }

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值