浏览 2875 次
锁定老帖子 主题:Tomcat源码---请求处理四(2)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-25
最后修改:2011-03-20
对以上的StandardWrapperValve#invoke进行说解
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[i]) == null) { parameters.put (paramNames[i], jspWrapper.findInitParameter(paramNames[i])); } } } } // 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
这里面对过滤器进行了执行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也已经执行....接下来做些释放工程 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-03-20
servlet的创建是一个单线程多实例的
是不是应该是多线程单实例? |
|
返回顶楼 | |
发表时间:2011-03-20
kyh23_y 写道 servlet的创建是一个单线程多实例的
是不是应该是多线程单实例? 呵呵,,,写错了,,,已经更正 |
|
返回顶楼 | |