Tomcat8.5源码分析-HostConfig
来源:互联网 发布:json转map 编辑:程序博客网 时间:2024/05/16 18:16
HostConfig
1. public void lifecycleEvent(LifecycleEvent event) { 2. 3. // Identify the host we are associated with 4. try { 5. host = (Host) event.getLifecycle(); 6. if (host instanceof StandardHost) { 7. setCopyXML(((StandardHost) host).isCopyXML()); 8. setDeployXML(((StandardHost) host).isDeployXML()); 9. setUnpackWARs(((StandardHost) host).isUnpackWARs()); 10. setContextClass(((StandardHost) host).getContextClass()); 11. } 12. } catch (ClassCastException e) { 13. log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e); 14. return; 15. } 16. 17. // Process the event that has occurred 18. if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) { 19. check(); 20. } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) { 21. beforeStart(); 22. } else if (event.getType().equals(Lifecycle.START_EVENT)) { 23. start();//StandHost.startInternal() 触发了这个事件 24. } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { 25. stop(); 26. } 27. }
首先这个方法会检验Host是否是我们需要的,然后由于我们改变了生命周期的状态,所以调用它的start()方法。我们接着看代码:
1. public void start() { 2. //进行日志的相关处理和jmx的注册 3. if (log.isDebugEnabled()) 4. log.debug(sm.getString("hostConfig.start")); 5. 6. try { 7. ObjectName hostON = host.getObjectName(); 8. oname = new ObjectName 9. (hostON.getDomain() + ":type=Deployer,host=" + host.getName()); 10. Registry.getRegistry(null, null).registerComponent 11. (this, oname, this.getClass().getName()); 12. } catch (Exception e) { 13. log.error(sm.getString("hostConfig.jmx.register", oname), e); 14. } 15. 16. if (!host.getAppBaseFile().isDirectory()) { 17. log.error(sm.getString("hostConfig.appBase", host.getName(), 18. host.getAppBaseFile().getPath())); 19. host.setDeployOnStartup(false); 20. host.setAutoDeploy(false); 21. } 22. /*部署应用*/ 23. if (host.getDeployOnStartup()) 24. deployApps();//context描述文件的部署,web目录的部署,WAR包的部署 25. 26. }
接着我们看deployApps():
1. protected void deployApps() { 2. 3. File appBase = host.getAppBaseFile(); 4. File configBase = host.getConfigBaseFile(); 5. String[] filteredAppPaths = filterAppPaths(appBase.list()); 6. // Deploy XML descriptors from configBase 7. deployDescriptors(configBase, configBase.list()); 8. // Deploy WARs 9. deployWARs(appBase, filteredAppPaths); 10. // Deploy expanded folders 11. deployDirectories(appBase, filteredAppPaths); 12. 13. }
我们只看这一个deployDescriptors描述文件的部署:
1. protected void deployDescriptors(File configBase, String[] files) { 2. 3. if (files == null) 4. return; 5. 6. ExecutorService es = host.getStartStopExecutor(); 7. List<Future<?>> results = new ArrayList<>(); 8. 9. for (int i = 0; i < files.length; i++) {/*扫描host配置文件的基础目录*/ 10. File contextXml = new File(configBase, files[i]); 11. 12. if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".xml")) {/*对于每个配置文件*/ 13. ContextName cn = new ContextName(files[i], true); 14. 15. if (isServiced(cn.getName()) || deploymentExists(cn.getName())) 16. continue; 17. 18. results.add( 19. es.submit(new DeployDescriptor(this, cn, contextXml)));/*由线程池完成解析部署,调用run()*/ 20. } 21. } 22. 23. for (Future<?> result : results) { 24. try { 25. result.get(); 26. } catch (Exception e) { 27. log.error(sm.getString( 28. "hostConfig.deployDescriptor.threaded.error"), e); 29. } 30. } 31. }
接着看它的代码:
2. private static class DeployDescriptor implements Runnable { 2. 3. private HostConfig config; 4. private ContextName cn; 5. private File descriptor; 6. 7. public DeployDescriptor(HostConfig config, ContextName cn, 8. File descriptor) { 9. this.config = config; 10. this.cn = cn; 11. this.descriptor= descriptor; 12. } 13. 14. @Override 15. public void run() { 16. config.deployDescriptor(cn, descriptor);/*线程调用方法*/ 17. } 18. }
继续看run方法:
1. protected void deployDescriptor(ContextName cn, File contextXml) { 2. 3. DeployedApplication deployedApp = 4. new DeployedApplication(cn.getName(), true); 5. 6. long startTime = 0; 7. // Assume this is a configuration descriptor and deploy it 8. if(log.isInfoEnabled()) { 9. startTime = System.currentTimeMillis(); 10. log.info(sm.getString("hostConfig.deployDescriptor", 11. contextXml.getAbsolutePath())); 12. } 13. 14. Context context = null; 15. boolean isExternalWar = false; 16. boolean isExternal = false; 17. File expandedDocBase = null; 18. 19. try (FileInputStream fis = new FileInputStream(contextXml)) { 20. synchronized (digesterLock) { 21. try { 22. context = (Context) digester.parse(fis);/*使用digester创建context实例*/ 23. } catch (Exception e) { 24. log.error(sm.getString( 25. "hostConfig.deployDescriptor.error", 26. contextXml.getAbsolutePath()), e); 27. } finally { 28. digester.reset(); 29. if (context == null) { 30. context = new FailedContext(); 31. } 32. } 33. }
digster解析的时候创建了对象:
1. Class<?> clazz = Class.forName(host.getConfigClass()); 2. LifecycleListener listener = 3. (LifecycleListener) clazz.newInstance(); 4. context.addLifecycleListener(listener);//为context添加生命周期监听器 5. 6. context.setConfigFile(contextXml.toURI().toURL());//设置context实例的ConfigFile 7. context.setName(cn.getName());//设置context实例的名称 8. context.setPath(cn.getPath());//设置context实例的路径 9. context.setWebappVersion(cn.getVersion()); 10. //设置context实例的版本 11. // Add the associated docBase to the redeployed list if it's a WAR 12. if (context.getDocBase() != null) { 13. File docBase = new File(context.getDocBase()); 14. if (!docBase.isAbsolute()) { 15. docBase = new File(host.getAppBaseFile(), context.getDocBase()); 16. } 17. // If external docBase, register .xml as redeploy first 18. if (!docBase.getCanonicalPath().startsWith( 19. host.getAppBaseFile().getAbsolutePath() + File.separator)) { 20. isExternal = true; 21. deployedApp.redeployResources.put( 22. contextXml.getAbsolutePath(), 23. Long.valueOf(contextXml.lastModified())); 24. deployedApp.redeployResources.put(docBase.getAbsolutePath(), 25. Long.valueOf(docBase.lastModified())); 26. if (docBase.getAbsolutePath().toLowerCase(Locale.ENGLISH).endsWith(".war")) { 27. isExternalWar = true; 28. } 29. } else { 30. log.warn(sm.getString("hostConfig.deployDescriptor.localDocBaseSpecified", 31. docBase)); 32. // Ignore specified docBase 33. context.setDocBase(null); 34. } 35. } 36. 37. host.addChild(context);//把context的实例添加到host 38. } catch (Throwable t) { 39. ExceptionUtils.handleThrowable(t); 40. log.error(sm.getString("hostConfig.deployDescriptor.error", 41. contextXml.getAbsolutePath()), t); 42. } finally { 43. // Get paths for WAR and expanded WAR in appBase 44. //获得WAR包的路径并且展开WAR包在appBase里面 45. // default to appBase dir + name 46. expandedDocBase = new File(host.getAppBaseFile(), cn.getBaseName()); 47. if (context.getDocBase() != null 48. && !context.getDocBase().toLowerCase(Locale.ENGLISH).endsWith(".war")) { 49. // first assume docBase is absolute 50. //先假定这个docBase的路径是绝对的 51. expandedDocBase = new File(context.getDocBase()); 52. if (!expandedDocBase.isAbsolute()) { 53. // if docBase specified and relative, it must be relative to appBase 54. //如果路径是相对的,那么它一定是相对于appBase 55. expandedDocBase = new File(host.getAppBaseFile(), context.getDocBase()); 56. } 57. } 58. 59. boolean unpackWAR = unpackWARs; 60. if (unpackWAR && context instanceof StandardContext) { 61. unpackWAR = ((StandardContext) context).getUnpackWAR(); 62. } 63. 64. // Add the eventual unpacked WAR and all the resources which will be 65. // watched inside it 66. //添加最终解开的WAR包 67. if (isExternalWar) { 68. if (unpackWAR) { 69. deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), 70. Long.valueOf(expandedDocBase.lastModified())); 71. addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), context); 72. } else { 73. addWatchedResources(deployedApp, null, context); 74. } 75. } else { 76. // Find an existing matching war and expanded folder 77. //找到已存在的匹配的war包并且展开文件夹 78. if (!isExternal) { 79. File warDocBase = new File(expandedDocBase.getAbsolutePath() + ".war"); 80. if (warDocBase.exists()) { 81. deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), 82. Long.valueOf(warDocBase.lastModified())); 83. } else { 84. // Trigger a redeploy if a WAR is added 85. //触发再次解析如果WAR包被添加进去 86. deployedApp.redeployResources.put( 87. warDocBase.getAbsolutePath(), 88. Long.valueOf(0)); 89. } 90. } 91. if (unpackWAR) { 92. deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), 93. Long.valueOf(expandedDocBase.lastModified())); 94. addWatchedResources(deployedApp, 95. expandedDocBase.getAbsolutePath(), context); 96. } else { 97. addWatchedResources(deployedApp, null, context); 98. } 99. if (!isExternal) { 100. // For external docBases, the context.xml will have been 101. // added above. 102. deployedApp.redeployResources.put( 103. contextXml.getAbsolutePath(), 104. Long.valueOf(contextXml.lastModified())); 105. } 106. } 107. // Add the global redeploy resources (which are never deleted) at 108. // the end so they don't interfere with the deletion process 109. addGlobalRedeployResources(deployedApp); 110. } 111. 112. if (host.findChild(context.getName()) != null) { 113. deployed.put(context.getName(), deployedApp); 114. } 115. 116. if (log.isInfoEnabled()) { 117. log.info(sm.getString("hostConfig.deployDescriptor.finished", 118. contextXml.getAbsolutePath(), Long.valueOf(System.currentTimeMillis() - startTime))); 119. } 120. }
再看这个方法:
1. public void addChild(Container child) { 2. 3. child.addLifecycleListener(new MemoryLeakTrackingListener()); 4. 5. if (!(child instanceof Context)) 6. throw new IllegalArgumentException 7. (sm.getString("standardHost.notContext")); 8. super.addChild(child);/*最终会调用child.start()方法,在containerBase里面*/ 9. 10. }
再看super.addChild():
public void addChild(Container child) { 2. if (Globals.IS_SECURITY_ENABLED) { 3. PrivilegedAction<Void> dp = 4. new PrivilegedAddChild(child); 5. AccessController.doPrivileged(dp); 6. } else { 7. addChildInternal(child); 8. } 9. }
其实不管怎么样都会调用addChildInternal(child),
继续看这个里面的代码:
1. private void addChildInternal(Container child) { 2. 3. if( log.isDebugEnabled() ) 4. log.debug("Add child " + child + " " + this); 5. synchronized(children) { 6. if (children.get(child.getName()) != null) 7. throw new IllegalArgumentException("addChild: Child name '" + 8. child.getName() + 9. "' is not unique"); 10. child.setParent(this); // May throw IAE 11. children.put(child.getName(), child); 12. } 13. 14. // Start child 15. // Don't do this inside sync block - start can be a slow process and 16. // locking the children object can cause problems elsewhere 17. try { 18. if ((getState().isAvailable() || 19. LifecycleState.STARTING_PREP.equals(getState())) && 20. startChildren) { 21. child.start();/*在这个地方调用的*/ 22. } 23. } catch (LifecycleException e) { 24. log.error("ContainerBase.addChild: start: ", e); 25. throw new IllegalStateException("ContainerBase.addChild: start: " + e); 26. } finally { 27. fireContainerEvent(ADD_CHILD_EVENT, child); 28. } 29. }
可以看到最终child.start(),在这个地方终于转向了StandardContext,
其他两个部署方法省略,感兴趣可以查看相关资料。
Tomcat8.5源码分析-StandardContext
阅读全文
0 0
- Tomcat8.5源码分析-HostConfig
- Tomcat8.5源码分析-StandardHost
- Tomcat8.5源码分析-StandardContext
- Tomcat8.5源码分析-ContextConfig
- Tomcat8.5源码分析-StandardWrapper
- Tomcat源码阅读之StandardHost与HostConfig的分析
- tomcat8关键性源码分析
- Tomcat8源码分析(一)
- Tomcat8源码分析(二)
- Tomcat8源码分析(三)
- Tomcat8源码分析(四)
- tomcat8源码分析(一):导入eclipse
- tomcat8源码导入
- Eclipse运行Tomcat8源码
- Tomcat8.0.0源码研读
- tomcat8 源码 导入eclipse
- HostConfig.deployDirectories
- Tomcat8.5.11源码导入Myeclipse
- android服务端与客户端
- Vasya is the beginning mathematician. He decided to make an important contribution to the science an
- js实现Div拖拽
- ActiveX控件属性:自定义属性的使用
- java 不规则二维数组的定义与输出 及 Arrays.fill(type[] A , type B)的用法 及 交换两行的方法
- Tomcat8.5源码分析-HostConfig
- HDU 2767 Proving Equivalences(强连通 Tarjan+缩点)
- Windows----搜狗输入法在word中中英文正常转换,在浏览器上只有英文
- AI看啥片
- Linux常用命令集
- Android 首页实现放大缩小的画廊效果
- X264码率控制总结
- Python里的那些坑
- android开发 之 android和js通过WebView调用