请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pi

首先,来看一下Servlet的载入过程。

具体是在org.apache.catalina.core.StandardWrapper#allocate()这个方法中,源代码如下:

Java代码 请求在Tomcat中传到了CoyoteAdapter的service()方法中后,就要准备进入Pi - guoyang1982 - 游龙

  1. public Servlet allocate() throws ServletException {   
  2.   
  3.     if (unloading)   
  4.         throw new ServletException(sm.getString("standardWrapper.unloading", getName()));   
  5.        
  6.     // 是否创建了新的实例   
  7.     boolean newInstance = false;   
  8.        
  9.     // 对非singleThreadModel的Servlet的处理   
  10.   
  11.     // 如果不是SingleThreadedModel,每次都返回相同的实例   
  12.     if (!singleThreadModel) {   
  13.   
  14.         // 初始化Servlet实例   
  15.         if (instance == null) {   
  16.             synchronized (this) {   
  17.                 if (instance == null) {   
  18.                     try {   
  19.                         if (log.isDebugEnabled())   
  20.                             log.debug("Allocating non-STM instance");   
  21.                         // 载入新的实例   
  22.                         instance = loadServlet();   
  23.   
  24.                         if (!singleThreadModel) {   
  25.                             newInstance = true;   
  26.                             // 计数器自增   
  27.                             countAllocated++;   
  28.                         }   
  29.                     } catch (ServletException e) {   
  30.                         throw e;   
  31.                     } catch (Throwable e) {   
  32.                         throw new ServletException(sm.getString("standardWrapper.allocate"), e);   
  33.                     }   
  34.                 }   
  35.             }   
  36.         }   
  37.   
  38.         if (!singleThreadModel) {   
  39.             if (log.isTraceEnabled())   
  40.                 log.trace("  Returning non-STM instance");   
  41.   
  42.             if (!newInstance) {// 没有创建新实例的时候的计数器自增   
  43.                 countAllocated++;   
  44.             }   
  45.             // 直接返回Servlet实例   
  46.             return (instance);   
  47.         }   
  48.     }   
  49.   
  50.     // 下边是对singleThreadModel的Servlet的处理   
  51.     synchronized (instancePool) {   
  52.   
  53.         while (countAllocated >= nInstances) {   
  54.             // Allocate a new instance if possible, or else wait   
  55.             if (nInstances < maxInstances) {   
  56.                 try {   
  57.                     // 将Servlet实例入栈   
  58.                     instancePool.push(loadServlet());   
  59.                     // 实例数自增   
  60.                     nInstances++;   
  61.                 } catch (ServletException e) {   
  62.                     throw e;   
  63.                 } catch (Throwable e) {   
  64.                     throw new ServletException(sm.getString("standardWrapper.allocate"), e);   
  65.                 }   
  66.             } else {   
  67.                 try {   
  68.                     instancePool.wait();   
  69.                 } catch (InterruptedException e) {   
  70.                     ;   
  71.                 }   
  72.             }   
  73.         }   
  74.         if (log.isTraceEnabled())   
  75.             log.trace("  Returning allocated STM instance");   
  76.         countAllocated++;   
  77.         return (Servlet) instancePool.pop();   
  78.   
  79.     }   
  80.   
  81. }  

这段代码分两种情况来载入Servlet实例,一种是singleThreadModel的,每个请求都要创建一个实例,这些实例是放到instancePool中的,另外一种是非singleThreadModel的,它对每一个请求线程都使用同一个实例。对于非singleThreadModel的Servlet,当第一次载入之后就不需要再次构建了。

下边来大概的看一下具体的载入Servelt的过程,就是#loadServlet()这个方法。方法的细节比较多,大致了解下,主要就是ClassLoader的构建,Servlet实例的创建和Servlet初始化方法的调用3个大的部分。源代码如下:

Java代码 请求在Tomcat中传到了CoyoteAdapter的service()方法中后,就要准备进入Pi - guoyang1982 - 游龙

  1. public synchronized Servlet loadServlet() throws ServletException {   
  2.   
  3.     // 非singleThreadModel模式并且instance已经实例化过的情况直接返回   
  4.     if (!singleThreadModel && (instance != null))   
  5.         return instance;   
  6.   
  7.     PrintStream out = System.out;   
  8.     if (swallowOutput) {   
  9.         SystemLogHandler.startCapture();   
  10.     }   
  11.   
  12.     Servlet servlet;   
  13.     try {   
  14.         long t1 = System.currentTimeMillis();   
  15.         // Servlet的完整类名   
  16.         String actualClass = servletClass;   
  17.         if ((actualClass == null) && (jspFile != null)) {// 如果是JSP文件   
  18.             Wrapper jspWrapper = (Wrapper) ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);   
  19.             if (jspWrapper != null) {   
  20.                 actualClass = jspWrapper.getServletClass();   
  21.                 // Merge init parameters   
  22.                 String paramNames[] = jspWrapper.findInitParameters();   
  23.                 for (int i = 0; i < paramNames.length; i++) {   
  24.                     if (parameters.get(paramNames[i]) == null) {   
  25.                         parameters.put(paramNames[i], jspWrapper.findInitParameter(paramNames[i]));   
  26.                     }   
  27.                 }   
  28.             }   
  29.         }   
  30.   
  31.         // Complain if no servlet class has been specified   
  32.         if (actualClass == null) {   
  33.             unavailable(null);   
  34.             throw new ServletException(sm.getString("standardWrapper.notClass", getName()));   
  35.         }   
  36.   
  37.         // 构建ClassLoader   
  38.         Loader loader = getLoader();   
  39.         if (loader == null) {   
  40.             unavailable(null);   
  41.             throw new ServletException(sm.getString("standardWrapper.missingLoader", getName()));   
  42.         }   
  43.   
  44.         ClassLoader classLoader = loader.getClassLoader();   
  45.   
  46.         if (isContainerProvidedServlet(actualClass) && !((Context) getParent()).getPrivileged()) {   
  47.             classLoader = this.getClass().getClassLoader();   
  48.         }   
  49.   
  50.         Class classClass = null;   
  51.         try {   
  52.             if (SecurityUtil.isPackageProtectionEnabled()) {   
  53.                 final ClassLoader fclassLoader = classLoader;   
  54.                 final String factualClass = actualClass;   
  55.                 try {   
  56.                     classClass = (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {   
  57.                         public Object run() throws Exception {   
  58.                             if (fclassLoader != null) {   
  59.                                 return fclassLoader.loadClass(factualClass);   
  60.                             } else {   
  61.                                 return Class.forName(factualClass);   
  62.                             }   
  63.                         }   
  64.                     });   
  65.                 } catch (PrivilegedActionException pax) {   
  66.                     Exception ex = pax.getException();   
  67.                     if (ex instanceof ClassNotFoundException) {   
  68.                         throw (ClassNotFoundException) ex;   
  69.                     } else {   
  70.                         getServletContext().log("Error loading " + fclassLoader + " " + factualClass, ex);   
  71.                     }   
  72.                 }   
  73.             } else {   
  74.                 if (classLoader != null) {   
  75.                     classClass = classLoader.loadClass(actualClass);   
  76.                 } else {   
  77.                     classClass = Class.forName(actualClass);   
  78.                 }   
  79.             }   
  80.         } catch (ClassNotFoundException e) {   
  81.             unavailable(null);   
  82.             getServletContext().log("Error loading " + classLoader + " " + actualClass, e);   
  83.             throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass), e);   
  84.         }   
  85.   
  86.         if (classClass == null) {   
  87.             unavailable(null);   
  88.             throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass));   
  89.         }   
  90.   
  91.         // 生成Servlet实例   
  92.         try {   
  93.             servlet = (Servlet) classClass.newInstance();   
  94.             if (!((Context) getParent()).getIgnoreAnnotations()) {   
  95.                 if (getParent() instanceof StandardContext) {   
  96.                     ((StandardContext) getParent()).getAnnotationProcessor().processAnnotations(servlet);   
  97.                     ((StandardContext) getParent()).getAnnotationProcessor().postConstruct(servlet);   
  98.                 }   
  99.             }   
  100.         } catch (ClassCastException e) {   
  101.             unavailable(null);   
  102.             throw new ServletException(sm.getString("standardWrapper.notServlet", actualClass), e);   
  103.         } catch (Throwable e) {   
  104.             unavailable(null);   
  105.             if (log.isDebugEnabled()) {   
  106.                 log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);   
  107.             }   
  108.   
  109.             throw new ServletException(sm.getString("standardWrapper.instantiate", actualClass), e);   
  110.         }   
  111.   
  112.         if (!isServletAllowed(servlet)) {   
  113.             throw new SecurityException(sm.getString("standardWrapper.privilegedServlet", actualClass));   
  114.         }   
  115.   
  116.         if ((servlet instanceof ContainerServlet)   
  117.                 && (isContainerProvidedServlet(actualClass) || ((Context) getParent()).getPrivileged())) {   
  118.             ((ContainerServlet) servlet).setWrapper(this);   
  119.         }   
  120.   
  121.         classLoadTime = (int) (System.currentTimeMillis() - t1);   
  122.   
  123.         // 调用Servelt的初始化方法   
  124.         try {   
  125.             instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);   
  126.   
  127.             if (Globals.IS_SECURITY_ENABLED) {   
  128.                 Object[] args = new Object[] { ((ServletConfig) facade) };   
  129.                 SecurityUtil.doAsPrivilege("init", servlet, classType, args);   
  130.                 args = null;   
  131.             } else {   
  132.                 servlet.init(facade);   
  133.             }   
  134.   
  135.             // Invoke jspInit on JSP pages   
  136.             if ((loadOnStartup >= 0) && (jspFile != null)) {   
  137.                 // 调用jspInit()   
  138.                 DummyRequest req = new DummyRequest();   
  139.                 req.setServletPath(jspFile);   
  140.                 req.setQueryString("jsp_precompile=true");   
  141.                 DummyResponse res = new DummyResponse();   
  142.   
  143.                 if (Globals.IS_SECURITY_ENABLED) {   
  144.                     Object[] args = new Object[] { req, res };   
  145.                     SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args);   
  146.                     args = null;   
  147.                 } else {   
  148.                     servlet.service(req, res);   
  149.                 }   
  150.             }   
  151.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);   
  152.         } catch (UnavailableException f) {   
  153.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);   
  154.             unavailable(f);   
  155.             throw f;   
  156.         } catch (ServletException f) {   
  157.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);   
  158.             throw f;   
  159.         } catch (Throwable f) {   
  160.             getServletContext().log("StandardWrapper.Throwable", f);   
  161.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);   
  162.             throw new ServletException(sm.getString("standardWrapper.initException", getName()), f);   
  163.         }   
  164.   
  165.         singleThreadModel = servlet instanceof SingleThreadModel;   
  166.         if (singleThreadModel) {   
  167.             if (instancePool == null)   
  168.                 instancePool = new Stack();   
  169.         }   
  170.         fireContainerEvent("load", this);   
  171.   
  172.         loadTime = System.currentTimeMillis() - t1;   
  173.     } finally {   
  174.         if (swallowOutput) {   
  175.             String log = SystemLogHandler.stopCapture();   
  176.             if (log != null && log.length() > 0) {   
  177.                 if (getServletContext() != null) {   
  178.                     getServletContext().log(log);   
  179.                 } else {   
  180.                     out.println(log);   
  181.                 }   
  182.             }   
  183.         }   
  184.     }   
  185.     return servlet;   
  186.   
  187. }  

另外,在载入JSP文件时,Servlet是org.apache.jasper.servlet.JspServlet的实例,载入静态资源时,Servlet用的是org.apache.catalina.servlets.DefaultServlet实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值