Tomcat请求处理(六) -- Servlet实例创建
来源:互联网 发布:新浪微博客户端mac版 编辑:程序博客网 时间:2024/06/05 10:23
首先,来看一下Servlet的载入过程。
具体是在org.apache.catalina.core.StandardWrapper#allocate()这个方法中,源代码如下:
这段代码分两种情况来载入Servlet实例,一种是singleThreadModel的,每个请求都要创建一个实例,这些实例是放到instancePool中的,另外一种是非singleThreadModel的,它对每一个请求线程都使用同一个实例。对于非singleThreadModel的Servlet,当第一次载入之后就不需要再次构建了。
下边来大概的看一下具体的载入Servelt的过程,就是#loadServlet()这个方法。方法的细节比较多,大致了解下,主要就是ClassLoader的构建,Servlet实例的创建和Servlet初始化方法的调用3个大的部分。源代码如下:
另外,在载入JSP文件时,Servlet是org.apache.jasper.servlet.JspServlet的实例,载入静态资源时,Servlet用的是org.apache.catalina.servlets.DefaultServlet实例。
而JSP页面在后边还有编译等操作,后边还要继续详述。
具体是在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
- Tomcat请求处理(六) -- Servlet实例创建
- tomcat请求处理分析(六)servlet的处理过程
- Tomcat请求处理(七) - Servlet实例的调用
- Servlet容器 - Tomcat请求处理原理
- servlet图解。1。。tomcat处理请求过程、servlet的生命周期
- Servlet之tomcat处理Http请求的流程
- Tomcat一次http请求处理,filter、servlet调用流程
- web请求:servlet处理请求
- tomcat请求处理分析(一) 启动container实例
- Servlet请求的处理
- Servlet处理HTTP请求
- servlet处理请求
- servlet处理http请求
- servlet处理http请求
- servlet多请求处理
- Servlet容器请求处理
- tomcat上servlet程序的配置与处理servlet请求过程
- Tomcat+Eclipse 创建Servlet
- Tomcat请求处理(七) - Servlet实例的调用
- Java Servlet 获取服务器各种路径信息
- 屏蔽“您目前使用的Discuz!程序有新版本发布,请及时升级!”提示
- HDOJ-2025解题报告
- iOS-CoreData
- Tomcat请求处理(六) -- Servlet实例创建
- vc 用函数读写INI配置文件
- Eclipse中用Git导入Maven项目
- linux service命令
- cocos2dx-弱联网
- 清空file文件上传域jquery与js方法
- 数据绑定之DataFormatString
- Tomcat请求处理(五) -- 请求在容器间的流动
- HDU 1517 A Multiplication Game(博弈入门)