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

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

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

	public Servlet allocate() throws ServletException {

		if (unloading)
			throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
		
		// 是否创建了新的实例
		boolean newInstance = false;
		
		// 对非singleThreadModel的Servlet的处理

		// 如果不是SingleThreadedModel,每次都返回相同的实例
		if (!singleThreadModel) {

			// 初始化Servlet实例
			if (instance == null) {
				synchronized (this) {
					if (instance == null) {
						try {
							if (log.isDebugEnabled())
								log.debug("Allocating non-STM instance");
							// 载入新的实例
							instance = loadServlet();

							if (!singleThreadModel) {
								newInstance = true;
								// 计数器自增
								countAllocated++;
							}
						} 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");

				if (!newInstance) {// 没有创建新实例的时候的计数器自增
					countAllocated++;
				}
				// 直接返回Servlet实例
				return (instance);
			}
		}

		// 下边是对singleThreadModel的Servlet的处理
		synchronized (instancePool) {

			while (countAllocated >= nInstances) {
				// Allocate a new instance if possible, or else wait
				if (nInstances < maxInstances) {
					try {
						// 将Servlet实例入栈
						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++;
			return (Servlet) instancePool.pop();

		}

	}


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

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

	public synchronized Servlet loadServlet() throws ServletException {

		// 非singleThreadModel模式并且instance已经实例化过的情况直接返回
		if (!singleThreadModel && (instance != null))
			return instance;

		PrintStream out = System.out;
		if (swallowOutput) {
			SystemLogHandler.startCapture();
		}

		Servlet servlet;
		try {
			long t1 = System.currentTimeMillis();
			// Servlet的完整类名
			String actualClass = servletClass;
			if ((actualClass == null) && (jspFile != null)) {// 如果是JSP文件
				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()));
			}

			// 构建ClassLoader
			Loader loader = getLoader();
			if (loader == null) {
				unavailable(null);
				throw new ServletException(sm.getString("standardWrapper.missingLoader", getName()));
			}

			ClassLoader classLoader = loader.getClassLoader();

			if (isContainerProvidedServlet(actualClass) && !((Context) getParent()).getPrivileged()) {
				classLoader = this.getClass().getClassLoader();
			}

			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));
			}

			// 生成Servlet实例
			try {
				servlet = (Servlet) classClass.newInstance();
				if (!((Context) getParent()).getIgnoreAnnotations()) {
					if (getParent() instanceof StandardContext) {
						((StandardContext) getParent()).getAnnotationProcessor().processAnnotations(servlet);
						((StandardContext) getParent()).getAnnotationProcessor().postConstruct(servlet);
					}
				}
			} catch (ClassCastException e) {
				unavailable(null);
				throw new ServletException(sm.getString("standardWrapper.notServlet", actualClass), e);
			} catch (Throwable e) {
				unavailable(null);
				if (log.isDebugEnabled()) {
					log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);
				}

				throw new ServletException(sm.getString("standardWrapper.instantiate", actualClass), e);
			}

			if (!isServletAllowed(servlet)) {
				throw new SecurityException(sm.getString("standardWrapper.privilegedServlet", actualClass));
			}

			if ((servlet instanceof ContainerServlet)
					&& (isContainerProvidedServlet(actualClass) || ((Context) getParent()).getPrivileged())) {
				((ContainerServlet) servlet).setWrapper(this);
			}

			classLoadTime = (int) (System.currentTimeMillis() - t1);

			// 调用Servelt的初始化方法
			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
				if ((loadOnStartup >= 0) && (jspFile != null)) {
					// 调用jspInit()
					DummyRequest req = new DummyRequest();
					req.setServletPath(jspFile);
					req.setQueryString("jsp_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);
				throw f;
			} catch (Throwable f) {
				getServletContext().log("StandardWrapper.Throwable", f);
				instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);
				throw new ServletException(sm.getString("standardWrapper.initException", getName()), f);
			}

			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;

	}

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

而JSP页面在后边还有编译等操作,后边还要继续详述。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值