How Tomcat Works(十四)

系统 1685 0

我们已经知道,在tomcat中有四种类型的servlet容器,分别为Engine、Host、Context 和Wrapper,本文接下来对tomcat中Wrapper接口的标准实现进行说明。

对于每个引入的HTTP请求,连接器都会调用与其关联的servlet容器的invoke()方法;然后,servlet容器会调用所有子容器的invoke()方法

这里面的流程通常是servlet容器调用其管道对象的invoke()方法,其管道对象的invoke()方法最后调用其基础阀,管道对象的基础阀里面会调用子容器的invoke()方法;子容器的invoke()方法的调用序列与之相同。

在tomcat中,servlet类可以实现javax.servlet.SingleThreadModel接口,这样的servlet类也称为SingleThreadModel(STM)servlet类;根据Servlet规范,实现此接口的目的是保证servlet实例一次只处理一个请求。

StandardWrapper对象的主要任务是载入它所代表的servlet类,并进行实例化;不过StandardWrapper类并不调用servlet的service方法,该任务由StandardWrapperValve对象(StandardWrapper实例的管道对象中的基础阀)完成;StandardWrapperValve对象通过调用StandardWrapper实例的allocate()方法获取servlet实例,在获取实例后,StandardWrapperValve实例就会调用servlet实例的service()方法

对于STM 类型的servlet类与非STM 类型的servlet类,StandardWrapper实例的载入方式是不一样的;对于非STM 类型的servlet类,StandardWrapper实例只会载入一次,对于随后的请求都会返回servlet的同一个实例,它假设该servlet类的service()方法在多线程环境中是线程安全的。

而对于STM 类型的servlet类,StandardWrapper实例必须保证每一时刻只能有一个线程在执行STM servlet类的service()方法;StandardWrapper实例通过将STM 类型的servlet实例保存在一个java.util.Stack类型的栈中

      
        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
      
      
         {
                            instance 
      
      =
      
         loadServlet();
                        } 
      
      
        catch
      
      
         (ServletException e) {
                            
      
      
        throw
      
      
         e;
                        } 
      
      
        catch
      
      
         (Throwable e) {
                            
      
      
        throw
      
      
        new
      
      
         ServletException
                                (sm.getString(
      
      "standardWrapper.allocate"
      
        ), e);
                        }
                    }
                }
            }

            
      
      
        if
      
       (!
      
        singleThreadModel) {
                
      
      
        if
      
       (debug >= 2
      
        )
                    log(
      
      "  Returning non-STM instance"
      
        );
                countAllocated
      
      ++
      
        ;
                
      
      
        return
      
      
         (instance);
            }

        }

        
      
      
        synchronized
      
      
         (instancePool) {

            
      
      
        while
      
       (countAllocated >=
      
         nInstances) {
                
      
      
        //
      
      
         Allocate a new instance if possible, or else wait
      
      
        if
      
       (nInstances <
      
         maxInstances) {
                    
      
      
        try
      
      
         {
                        instancePool.push(loadServlet());
                        nInstances
      
      ++
      
        ;
                    } 
      
      
        catch
      
      
         (ServletException e) {
                        
      
      
        throw
      
      
         e;
                    } 
      
      
        catch
      
      
         (Throwable e) {
                        
      
      
        throw
      
      
        new
      
      
         ServletException
                            (sm.getString(
      
      "standardWrapper.allocate"
      
        ), e);
                    }
                } 
      
      
        else
      
      
         {
                    
      
      
        try
      
      
         {
                        instancePool.wait();
                    } 
      
      
        catch
      
      
         (InterruptedException e) {
                        ;
                    }
                }
            }
            
      
      
        if
      
       (debug >= 2
      
        )
                log(
      
      "  Returning allocated STM instance"
      
        );
            countAllocated
      
      ++
      
        ;
            
      
      
        return
      
      
         (Servlet) instancePool.pop();

        }

    }
      
    

而在loadServlet()方法中,首先获取要加载的servlet的完整类名及类加载器,然后通过类加载器加载该servlet类,然后实例化该servlet类,最后调用该servlet实例的init()方法初始化(传入javax.servlet.ServletConfig对象)

      
        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
      
      
            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
      
      
         {
                
      
      
        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) 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(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
      
      
            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);
                }
            }
        }
        
      
      
        return
      
      
         servlet;

    }
      
    

 StandardWrapper类的loadServlet()方法在载入servlet类后,会调用该servlet实例的init()方法,该方法需要传入一个javax.servlet.ServletConfig实例作为参数;那么, StandardWrapper对象是如何获取ServletConfig对象的呢

答案就在StandardWrapper类本身,该类不仅实现了Wrapper接口,还实现了javax.servlet.ServletConfig接口,下面是相关方法实现

      
        /**
      
      
        
     * Return the initialization parameter value for the specified name,
     * if any; otherwise return <code>null</code>.
     *
     * 
      
      
        @param
      
      
         name Name of the initialization parameter to retrieve
     
      
      
        */
      
      
        public
      
      
         String getInitParameter(String name) {

        
      
      
        return
      
      
         (findInitParameter(name));

    }


    
      
      
        /**
      
      
        
     * Return the set of initialization parameter names defined for this
     * servlet.  If none are defined, an empty Enumeration is returned.
     
      
      
        */
      
      
        public
      
      
         Enumeration getInitParameterNames() {

        
      
      
        synchronized
      
      
         (parameters) {
            
      
      
        return
      
       (
      
        new
      
      
         Enumerator(parameters.keySet()));
        }

    }


    
      
      
        /**
      
      
        
     * Return the servlet context with which this servlet is associated.
     
      
      
        */
      
      
        public
      
      
         ServletContext getServletContext() {

        
      
      
        if
      
       (parent == 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        null
      
      
        );
        
      
      
        else
      
      
        if
      
       (!(parent 
      
        instanceof
      
      
         Context))
            
      
      
        return
      
       (
      
        null
      
      
        );
        
      
      
        else
      
      
        return
      
      
         (((Context) parent).getServletContext());

    }


    
      
      
        /**
      
      
        
     * Return the name of this servlet.
     
      
      
        */
      
      
        public
      
      
         String getServletName() {

        
      
      
        return
      
      
         (getName());

    }
      
    

StandardWrapper实例在它的loadServlet()方法里面调用它所载入的servlet类的实例的init()方法,该方法需要一个javax.servlet.ServletConfig类型参数,理论上StandardWrapper对象可以将自身传入init()方法,不过为了类型安全,StandardWrapper类将自身实例包装成StandardWrapperFacade类的一个实例,然后再传给init()方法

      
        public
      
      
        final
      
      
        class
      
      
         StandardWrapperFacade
    
      
      
        implements
      
      
         ServletConfig {
    
      
      
        /**
      
      
        
     * Create a new facede around a StandardWrapper.
     
      
      
        */
      
      
        public
      
      
         StandardWrapperFacade(StandardWrapper config) {

        
      
      
        super
      
      
        ();
        
      
      
        this
      
      .config =
      
         (ServletConfig) config;

    }
      
      
        /**
      
      
        
     * Wrapped config.
     
      
      
        */
      
      
        private
      
       ServletConfig config = 
      
        null
      
      
        ;
      
      
        public
      
      
         String getServletName() {
        
      
      
        return
      
      
         config.getServletName();
    }

    
      
      
        public
      
      
         ServletContext getServletContext() {
        ServletContext theContext 
      
      =
      
         config.getServletContext();
        
      
      
        if
      
       ((theContext != 
      
        null
      
      ) &&
      
        
            (theContext 
      
      
        instanceof
      
      
         ApplicationContext))
            theContext 
      
      =
      
         ((ApplicationContext) theContext).getFacade();
        
      
      
        return
      
      
         (theContext);
    }

    
      
      
        public
      
      
         String getInitParameter(String name) {
        
      
      
        return
      
      
         config.getInitParameter(name);
    }

    
      
      
        public
      
      
         Enumeration getInitParameterNames() {
        
      
      
        return
      
      
         config.getInitParameterNames();
    }

}
      
    

StandardWrapperValve类是StandardWrapper实例中的基础阀,要完成两个操作

(1)执行与该servlet相关联的全部过滤器

(2)调用servlet实例的service()方法

      
        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()) {
            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) {
                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
      
      
        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
      
      
        )) {
                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);
            
      
      
        //
      
      
                    throwable = e;
            
      
      
        //
      
      
                    exception(request, response, 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
      
      
        ) {
                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)) {
                wrapper.unload();
            }
        } 
      
      
        catch
      
      
         (Throwable e) {
            log(sm.getString(
      
      "standardWrapper.unloadException"
      
        ,
                             wrapper.getName()), e);
            
      
      
        if
      
       (throwable == 
      
        null
      
      
        ) {
                throwable 
      
      =
      
         e;
                exception(request, response, e);
            }
        }

    }
      
    

上述创建过滤器链的过程本人后来作了补充: How Tomcat Works(十四)补充

--------------------------------------------------------------------------- 

本系列How Tomcat Works系本人原创 

转载请注明出处 博客园 刺猬的温驯 

本人邮箱:   chenying998179 # 163.com ( #改为@

本文链接 http://www.cnblogs.com/chenying99/p/3242278.html

How Tomcat Works(十四)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论