tomcat源码解析--StandardWrapperValve

StandardWrapperValve wrapper的最后一个valve,进入servlet之前的最后一步

invoke方法

先判断context和wrapper的 是否可用

if (!context.getAvailable()) {
        	response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                           sm.getString("standardContext.isUnavailable"));
            unavailable = true;
        }

        // Check for the servlet being marked unavailable
        if (!unavailable && wrapper.isUnavailable()) {
            container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
                    wrapper.getName()));
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                        sm.getString("standardWrapper.isUnavailable",
                                wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND,
                        sm.getString("standardWrapper.notFound",
                                wrapper.getName()));
            }
            unavailable = true;
        }

 加载servlet

if (!unavailable) {
                servlet = wrapper.allocate();
            }

 allocate方法

   boolean newInstance = false;
        
        // 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 {
                            if (log.isDebugEnabled())
                                log.debug("Allocating non-STM instance");

                            instance = loadServlet();
                            // For non-STM, increment here to prevent a race
                            // condition with unload. Bug 43683, test case #3
                            if (!singleThreadModel) {
                                newInstance = true;
                                countAllocated.incrementAndGet();
                            }
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            throw new ServletException
                                (sm.getString("standardWrapper.allocate"), e);
                        }
                    }
                }
            }

 loadServlet 方法

扫描二维码关注公众号,回复: 589003 查看本文章

1. 对于JSP 的处理

String actualClass = servletClass;
            if ((actualClass == null) && (jspFile != null)) {
                Wrapper jspWrapper = (Wrapper)
                    ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
                if (jspWrapper != null) {
                    actualClass = jspWrapper.getServletClass();
                    // Merge init parameters
                    String paramNames[] = jspWrapper.findInitParameters();
                    for (int i = 0; i < paramNames.length; i++) {
                        if (parameters.get(paramNames[i]) == null) {
                            parameters.put
                                (paramNames[i], 
                                 jspWrapper.findInitParameter(paramNames[i]));
                        }
                    }
                }

 设置classloader,默认为loader的classloader,如果是 ContainerServlet 的子类或者 org.apache.catalina包下的,则设置当前的classloader

ClassLoader classLoader = loader.getClassLoader();

            // Special case class loader for a container provided servlet
            //  
            if (isContainerProvidedServlet(actualClass) && 
                    ! ((Context)getParent()).getPrivileged() ) {
                // If it is a priviledged context - using its own
                // class loader will work, since it's a child of the container
                // loader
                classLoader = this.getClass().getClassLoader();
            }

 加载servlet class,如果是包限制的,则特殊处理

if (SecurityUtil.isPackageProtectionEnabled()){
                    final ClassLoader fclassLoader = classLoader;
                    final String factualClass = actualClass;
                    try{
                        classClass = (Class)AccessController.doPrivileged(
                                new PrivilegedExceptionAction(){
                                    public Object run() throws Exception{
                                        if (fclassLoader != null) {
                                            return fclassLoader.loadClass(factualClass);
                                        } else {
                                            return Class.forName(factualClass);
                                        }
                                    }
                        });
                    } catch(PrivilegedActionException pax){
                        Exception ex = pax.getException();
                        if (ex instanceof ClassNotFoundException){
                            throw (ClassNotFoundException)ex;
                        } else {
                            getServletContext().log( "Error loading "
                                + fclassLoader + " " + factualClass, ex );
                        }
                    }
                } else {
                    if (classLoader != null) {
                        classClass = classLoader.loadClass(actualClass);
                    } else {
                        classClass = Class.forName(actualClass);
                    }
                }

创建servlet 实例,处理注解(StandardContext的AnnotationProcessor??)

 servlet = (Servlet) classClass.newInstance();
                // Annotation processing
                if (!((Context) getParent()).getIgnoreAnnotations()) {
                    if (getParent() instanceof StandardContext) {
                       ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);
                       ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);
                    }
                }

 触发 before_init_event

instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
                                                  servlet);

 servlet init方法调用,对于设置SecurityManager的特殊对待(SecurityUtil???)

                if( Globals.IS_SECURITY_ENABLED) {
                    boolean success = false;
                    try {
                        Object[] args = new Object[]{ facade };
                        SecurityUtil.doAsPrivilege("init",
                                                   servlet,
                                                   classType,
                                                   args);
                        success = true;
                    } finally {
                        if (!success) {
                            // destroy() will not be called, thus clear the reference now
                            SecurityUtil.remove(servlet);
                        }
                    }
                } else {
                    servlet.init(facade);
                }

 JSP 处理,直接调用service了

if ((loadOnStartup >= 0) && (jspFile != null)) {
                    // Invoking jspInit
                    DummyRequest req = new DummyRequest();
                    req.setServletPath(jspFile);
                    req.setQueryString(Constants.PRECOMPILE + "=true");
                    DummyResponse res = new DummyResponse();

                    if( Globals.IS_SECURITY_ENABLED) {
                        Object[] args = new Object[]{req, res};
                        SecurityUtil.doAsPrivilege("service",
                                                   servlet,
                                                   classTypeUsedInService,
                                                   args);
                        args = null;
                    } else {
                        servlet.service(req, res);
                    }
                }

 并且还会判断servlet是否 SingleThreadModel 子类,如果是会创建相关的instancePool

singleThreadModel = servlet instanceof SingleThreadModel;
            if (singleThreadModel) {
                if (instancePool == null)
                    instancePool = new Stack();
            }

 触发load事件

 fireContainerEvent("load", this);

 对于非多线程的servlet,池的处理

synchronized (instancePool) {

            while (countAllocated.get() >= 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 (log.isTraceEnabled())
                log.trace("  Returning allocated STM instance");
            countAllocated.incrementAndGet();
            return (Servlet) instancePool.pop();

        }

 allocate 结束

获取过滤器链

ApplicationFilterFactory factory =
            ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain =
            factory.createFilterChain(request, wrapper, servlet);

 过滤器处理

if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (comet) {
                            filterChain.doFilterEvent(request.getEvent());
                            request.setComet(true);
                        } else {
                            filterChain.doFilter(request.getRequest(), 
                                    response.getResponse());
                        }
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    if (comet) {
                        request.setComet(true);
                        filterChain.doFilterEvent(request.getEvent());
                    } else {
                        filterChain.doFilter
                            (request.getRequest(), response.getResponse());
                    }
                }

            }

 ApplicationFilterChain.doFilter方法调用internalDoFilter方法处理

filter 遍历处理

ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = null;
            try {
                filter = filterConfig.getFilter();
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
                                          filter, request, response);
                
                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);
                    
                    args = null;
                } else {  
                    filter.doFilter(request, response, this);
                }

                support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                                          filter, request, response);

 service 方法调用

support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                                      servlet, request, response);
            if ((request instanceof HttpServletRequest) &&
                (response instanceof HttpServletResponse)) {
                    
                if( 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);   
                    args = null;
                } else {  
                    servlet.service((HttpServletRequest) request,
                                    (HttpServletResponse) response);
                }
            } else {
                servlet.service(request, response);
            }
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response);

 调用结束,开始善后

过滤器标志回滚

if (filterChain != null) {
            if (request.isComet()) {
                // If this is a Comet request, then the same chain will be used for the
                // processing of all subsequent events.
                filterChain.reuse();
            } else {
                filterChain.release();
            }
        }

 如果有servlet 池,释放当前servlet

if (servlet != null) {
                wrapper.deallocate(servlet);
            }

 释放当前servlet在 wrapper中

if ((servlet != null) &&
                (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }

猜你喜欢

转载自patrick002.iteye.com/blog/2144194