六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 96|回复: 0

Tomcat源码---请求处理四(2)

[复制链接]

升级  18%

19

主题

19

主题

19

主题

秀才

Rank: 2

积分
77
 楼主| 发表于 2013-2-6 10:20:46 | 显示全部楼层 |阅读模式
对以上的StandardWrapperValve#invoke进行说解
 

  •   if (!unavailable) {  
  •                 //servlet行行在这一步  
  •                 servlet = wrapper.allocate();  
  •             }  
 
 
public Servlet allocate() throws ServletException {        // If we are currently unloading this servlet, throw an exception        if (unloading)            throw new ServletException              (sm.getString("standardWrapper.unloading", getName()));        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);                        }                    }                }            }            if (!singleThreadModel) {                if (log.isTraceEnabled())                    log.trace("  Returning non-STM instance");                // For new instances, count will have been incremented at the                // time of creation                if (!newInstance) {                    countAllocated.incrementAndGet();                }                return (instance);            }        }        //每一次都返回一个实例存放在instancePool中        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();        }    }   以上这一步在我们平时使用时会经常遇到,,servlet的创建是一个多线程单实例的,所以共享全局变量,所以在使用servlet
时应尽量避免定义全局变量
对#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;        if (swallowOutput) {            SystemLogHandler.startCapture();        }        Servlet servlet;        try {            long t1=System.currentTimeMillis();            // 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();                    // Merge init parameters                    String paramNames[] = jspWrapper.findInitParameters();                    for (int i = 0; i < paramNames.length; i++) {                        if (parameters.get(paramNames) == null) {                            parameters.put                                (paramNames,                                  jspWrapper.findInitParameter(paramNames));                        }                    }                }            }            // 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()));            }            //获取werbappclassloader            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();            }            // Load the specified servlet class from the appropriate class loader            Class classClass = null;            try {                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);                    }                }            } catch (ClassNotFoundException e) {                unavailable(null);                getServletContext().log( "Error loading " + classLoader + " " + actualClass, e );                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();                // Annotation processing                if (!((Context) getParent()).getIgnoreAnnotations()) {                    if (getParent() instanceof StandardContext) {                       ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);                       ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);                    }                }            } catch (ClassCastException e) {                unavailable(null);                // Restore the context ClassLoader                throw new ServletException                    (sm.getString("standardWrapper.notServlet", actualClass), e);            } catch (Throwable e) {                unavailable(null);                              // Added extra log statement for Bugzilla 36630:                // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630                if(log.isDebugEnabled()) {                    log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);                }                // 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) ||                    ((Context)getParent()).getPrivileged() )) {                ((ContainerServlet) servlet).setWrapper(this);            }            classLoadTime=(int) (System.currentTimeMillis() -t1);            // Call the initialization method of this servlet           //该Servlet的初始化,只实现一次            try {                instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,                                                  servlet);                if( Globals.IS_SECURITY_ENABLED) {                    Object[] args = new Object[]{((ServletConfig)facade)};                    SecurityUtil.doAsPrivilege("init",                                               servlet,                                               classType,                                               args);                    args = null;                } else {                    servlet.init(facade);                }                // Invoke jspInit on JSP pages                //jsp转换成servlet的初始化                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);                    }                }                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) {                getServletContext().log("StandardWrapper.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);            loadTime=System.currentTimeMillis() -t1;        } finally {            if (swallowOutput) {                String log = SystemLogHandler.stopCapture();                if (log != null && log.length() > 0) {                    if (getServletContext() != null) {                        getServletContext().log(log);                    } else {                        out.println(log);                    }                }            }        }        return servlet;    } 从以上步骤可得到该servlet的实例,并用已经初始化过
现在对StandardWrapperValve#invoke
 

  •       //这里面开始对过滤器进行处理  
  •                             filterChain.doFilter(request.getRequest(),   
  •                                     response.getResponse()); 
 
这里面对过滤器进行了执行ApplicationFilterChain#doFilter
 
public void doFilter(ServletRequest request, ServletResponse response)        throws IOException, ServletException {        if( Globals.IS_SECURITY_ENABLED ) {            final ServletRequest req = request;            final ServletResponse res = response;            try {                java.security.AccessController.doPrivileged(                    new java.security.PrivilegedExceptionAction() {                        public Object 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);        }    } #internalDoFilter(rquest,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++];            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);            } catch (IOException e) {                if (filter != null)                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,                                              filter, request, response, e);                throw e;            } catch (ServletException e) {                if (filter != null)                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,                                              filter, request, response, e);                throw e;            } catch (RuntimeException e) {                if (filter != null)                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,                                              filter, request, response, e);                throw e;            } catch (Throwable e) {                if (filter != null)                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,                                              filter, request, response, e);                throw new ServletException                  (sm.getString("filterChain.filter"), e);            }            return;        }        // We fell off the end of the chain -- call the servlet instance        try {            if (Globals.STRICT_SERVLET_COMPLIANCE) {                lastServicedRequest.set(request);                lastServicedResponse.set(response);            }            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的方法                servlet.service(request, response);            }            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,                                      servlet, request, response);        } catch (IOException e) {            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,                                      servlet, request, response, e);            throw e;        } catch (ServletException e) {            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,                                      servlet, request, response, e);            throw e;        } catch (RuntimeException e) {            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,                                      servlet, request, response, e);            throw e;        } catch (Throwable e) {            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,                                      servlet, request, response, e);            throw new ServletException              (sm.getString("filterChain.servlet"), e);        } finally {            if (Globals.STRICT_SERVLET_COMPLIANCE) {                lastServicedRequest.set(null);                lastServicedResponse.set(null);            }        }    } 这样的过滤器已经执行,servlet也已经执行....接下来做些释放工程
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表