Tomcat8.5源码分析-StandardContext
来源:互联网 发布:java计算天干地支 编辑:程序博客网 时间:2024/05/22 00:08
StandardContext
直接看代码,相关操作已经打上注释:
protected synchronized void startInternal() throws LifecycleException { if(log.isDebugEnabled()) log.debug("Starting " + getBaseName()); // Send j2ee.state.starting notification //发送正在启动的通知 if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.state.starting", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } setConfigured(false); boolean ok = true; // Currently this is effectively a NO-OP but needs to be called to // ensure the NamingResources follows the correct lifecycle //启动context维护的JNDI资源 if (namingResources != null) { namingResources.start(); } // Add missing components as necessary if (getResources() == null) { // (1) Required by Loader if (log.isDebugEnabled()) log.debug("Configuring default Resources"); try { setResources(new StandardRoot(this));//初始化当前的webResourceRoot } catch (IllegalArgumentException e) { log.error(sm.getString("standardContext.resourcesInit"), e); ok = false; } } if (ok) { resourcesStart();//启动当前的webRecourseRoot,主要用于类加载和按照路径查找资源文件 } //创建web应用加载器 if (getLoader() == null) { WebappLoader webappLoader = new WebappLoader(getParentClassLoader()); webappLoader.setDelegate(getDelegate()); setLoader(webappLoader); } // An explicit cookie processor hasn't been specified; use the default //如果没有指定一个明确的cookie,使用默认的 if (cookieProcessor == null) { cookieProcessor = new Rfc6265CookieProcessor(); } // Initialize character set mapper //初始化字符集映射 getCharsetMapper(); // Post work directory //传递工作目录 postWorkDirectory(); // Validate required extensions boolean dependencyCheck = true; try { dependencyCheck = ExtensionValidator.validateApplication (getResources(), this); } catch (IOException ioe) { log.error(sm.getString("standardContext.extensionValidationError"), ioe); dependencyCheck = false; } //web应用的依赖检测,主要用来检测依赖拓展点的完整性 if (!dependencyCheck) { // do not make application available if dependency check fails ok = false; } // Reading the "catalina.useNaming" environment variable String useNamingProperty = System.getProperty("catalina.useNaming"); if ((useNamingProperty != null) && (useNamingProperty.equals("false"))) { useNaming = false; } //如果当前context使用了JNDI,就为它添加监听器NamingContextListener if (ok && isUseNaming()) { if (getNamingContextListener() == null) { NamingContextListener ncl = new NamingContextListener(); ncl.setName(getNamingContextName()); ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite()); addLifecycleListener(ncl); setNamingContextListener(ncl); } } // Standard container startup if (log.isDebugEnabled()) log.debug("Processing standard container startup"); // Binding thread //绑定线程 ClassLoader oldCCL = bindThread(); try { if (ok) { // Start our subordinate components, if any //开始我们的下一级别组件,如果有 Loader loader = getLoader(); if (loader instanceof Lifecycle) { ((Lifecycle) loader).start();//启动webAppLoader } // since the loader just started, the webapp classloader is now // created. setClassLoaderProperty("clearReferencesRmiTargets", getClearReferencesRmiTargets()); setClassLoaderProperty("clearReferencesStopThreads", getClearReferencesStopThreads()); setClassLoaderProperty("clearReferencesStopTimerThreads", getClearReferencesStopTimerThreads()); setClassLoaderProperty("clearReferencesHttpClientKeepAliveThread", getClearReferencesHttpClientKeepAliveThread()); // By calling unbindThread and bindThread in a row, we setup the // current Thread CCL to be the webapp classloader unbindThread(oldCCL); oldCCL = bindThread(); // Initialize logger again. Other components might have used it // too early, so it should be reset. logger = null; getLogger(); Realm realm = getRealmInternal(); if(null != realm) { if (realm instanceof Lifecycle) { ((Lifecycle) realm).start();//启动安全组件 } // Place the CredentialHandler into the ServletContext so // applications can have access to it. Wrap it in a "safe" // handler so application's can't modify it. CredentialHandler safeHandler = new CredentialHandler() { @Override public boolean matches(String inputCredentials, String storedCredentials) { return getRealmInternal().getCredentialHandler().matches(inputCredentials, storedCredentials); } @Override public String mutate(String inputCredentials) { return getRealmInternal().getCredentialHandler().mutate(inputCredentials); } }; context.setAttribute(Globals.CREDENTIAL_HANDLER, safeHandler); } // Notify our interested LifecycleListeners //通知我们的相关的生命监听器 fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);//触发生命周期监听器 // Start our child containers, if not already started for (Container child : findChildren()) { if (!child.getState().isAvailable()) { child.start();//启动context的子节点wrapper } } // Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).start();//启动context所维护的pipeline } // Acquire clustered manager //创建会话管理器,如果有集群,由集群配置,否则由StandardManager() Manager contextManager = null; Manager manager = getManager(); if (manager == null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.cluster.noManager", Boolean.valueOf((getCluster() != null)), Boolean.valueOf(distributable))); } if ( (getCluster() != null) && distributable) { try { contextManager = getCluster().createManager(getName()); } catch (Exception ex) { log.error("standardContext.clusterFail", ex); ok = false; } } else { contextManager = new StandardManager(); } } // Configure default manager if none was specified //如果没有被指定配置默认的会话管理器 if (contextManager != null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.manager", contextManager.getClass().getName())); } setManager(contextManager); } if (manager!=null && (getCluster() != null) && distributable) { //let the cluster know that there is a context that is distributable //and that it has its own manager getCluster().registerManager(manager); } } if (!getConfigured()) { log.error(sm.getString("standardContext.configurationFail")); ok = false; } // We put the resources into the servlet context //我们把资源(WebResourceRoot里面的资源)放到servletContext里面去 if (ok) getServletContext().setAttribute (Globals.RESOURCES_ATTR, getResources()); if (ok ) { if (getInstanceManager() == null) { javax.naming.Context context = null; if (isUseNaming() && getNamingContextListener() != null) { context = getNamingContextListener().getEnvContext(); } Map<String, Map<String, String>> injectionMap = buildInjectionMap( getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources()); setInstanceManager(new DefaultInstanceManager(context, injectionMap, this, this.getClass().getClassLoader()));//创建实例对象管理器,用于创建实例对象,如servlet,Filter } getServletContext().setAttribute( InstanceManager.class.getName(), getInstanceManager()); InstanceManagerBindings.bind(getLoader().getClassLoader(), getInstanceManager()); } // Create context attributes that will be required //将jar包扫描器放到ServletContext的属性里面去 if (ok) { getServletContext().setAttribute( JarScanner.class.getName(), getJarScanner()); } // Set up the context init params //合并ServletContext参数和ApplicationParmeter的参数 mergeParameters(); // Call ServletContainerInitializers添加web应用的配置,如servlet,Filter //调用这个方法以可编程的方式添加 for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry : initializers.entrySet()) { try { entry.getKey().onStartup(entry.getValue(), getServletContext()); } catch (ServletException e) { log.error(sm.getString("standardContext.sciFail"), e); ok = false; break; } } // Configure and call application event listeners //实例化应用监听器 if (ok) { if (!listenerStart()) { log.error(sm.getString("standardContext.listenerFail")); ok = false; } } // Check constraints for uncovered HTTP methods // Needs to be after SCIs and listeners as they may programmatically // change constraints //检测未覆盖的http方法的安全约束 if (ok) { checkConstraintsForUncoveredMethods(findConstraints()); } try { // Start manager //启动会话管理器 Manager manager = getManager(); if (manager instanceof Lifecycle) { ((Lifecycle) manager).start(); } } catch(Exception e) { log.error(sm.getString("standardContext.managerFail"), e); ok = false; } // Configure and call application filters //配置并且调用应用过滤器 if (ok) { if (!filterStart()) { log.error(sm.getString("standardContext.filterFail")); ok = false; } } // Load and initialize all "load on startup" servlets //实例化servlet if (ok) { if (!loadOnStartup(findChildren())){ log.error(sm.getString("standardContext.servletFail")); ok = false; } } // Start ContainerBackgroundProcessor thread //开始后台的进程 super.threadStart(); } finally { // Unbinding thread unbindThread(oldCCL); } // Set available status depending upon startup success if (ok) { if (log.isDebugEnabled()) log.debug("Starting completed"); } else { log.error(sm.getString("standardContext.startFailed", getName())); } startTime=System.currentTimeMillis(); // Send j2ee.state.running notification //发布正在运行的JMX通知 if (ok && (this.getObjectName() != null)) { Notification notification = new Notification("j2ee.state.running", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } // The WebResources implementation caches references to JAR files. On // some platforms these references may lock the JAR files. Since web // application start is likely to have read from lots of JARs, trigger // a clean-up now. //释放资源 getResources().gc(); // Reinitializing if something went wrong if (!ok) { setState(LifecycleState.FAILED); } else { setState(LifecycleState.STARTING); } }
看这一行代码,触发了生命周期事件,这个监听器是ContextConfig,相关操作在ContextConfig章节里面进行分析。
再看这一行代码,初始化了servlet
看load on startup这个方法:
public boolean loadOnStartup(Container children[]) { // Collect "load on startup" servlets that need to be initialized TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>(); for (int i = 0; i < children.length; i++) { Wrapper wrapper = (Wrapper) children[i]; int loadOnStartup = wrapper.getLoadOnStartup(); if (loadOnStartup < 0) continue; Integer key = Integer.valueOf(loadOnStartup); ArrayList<Wrapper> list = map.get(key); if (list == null) { list = new ArrayList<>(); map.put(key, list); } list.add(wrapper); } // Load the collected "load on startup" servlets for (ArrayList<Wrapper> list : map.values()) { for (Wrapper wrapper : list) { try { wrapper.load();/*实例化servlet并对servlet进行初始化*/ } catch (ServletException e) { getLogger().error(sm.getString("standardContext.loadOnStartup.loadException", getName(), wrapper.getName()), StandardWrapper.getRootCause(e)); // NOTE: load errors (including a servlet that throws // UnavailableException from the init() method) are NOT // fatal to application startup // unless failCtxIfServletStartFails="true" is specified if(getComputedFailCtxIfServletStartFails()) { return false; } } } } return true; }
可以看到最终转向了StandardWrapper。
Tomcat8.5源码分析—ContextConfig
阅读全文
0 0
- Tomcat8.5源码分析-StandardContext
- Tomcat8.5源码分析-StandardHost
- Tomcat8.5源码分析-HostConfig
- Tomcat8.5源码分析-ContextConfig
- Tomcat8.5源码分析-StandardWrapper
- tomcat8关键性源码分析
- Tomcat8源码分析(一)
- Tomcat8源码分析(二)
- Tomcat8源码分析(三)
- Tomcat8源码分析(四)
- tomcat8源码分析(一):导入eclipse
- Tomcat源码解析(三):StandardContext
- tomcat8源码导入
- Eclipse运行Tomcat8源码
- Tomcat8.0.0源码研读
- tomcat8 源码 导入eclipse
- tomcat(12)org.apache.catalina.core.StandardContext源码剖析
- Tomcat8.5.11源码导入Myeclipse
- sonar 安装运行
- git clone、push 提示输入密码但输入后登录被拒绝
- [JAVAWEB]5.详解JSP的运行原理
- Mybatis和spring整合
- iOS国际化
- Tomcat8.5源码分析-StandardContext
- 数据库水平切分
- javaScript高级程序设计 第1章 javaScript简介 思维导图笔记
- tensorflow regularizer(正则化)防止过拟合
- window下MongoDB的配置与安装
- 支付的典型架构
- 万物初始
- HDU
- Matlab转c与c++代码