Tomcat Server之启动---Bootstrap类
Tomcat虽然作为轻量级的Web Server,但是其设计精巧,作为一个Server,方方面面的知识都有涉及。今天我们就来研究一下他的启动类Bootstrap。
一、Class Bootstrap
Bootstrap类作为程序的入口自然是main(),而跟Bootstrap启动类相关的有:
ClassLoaderFactory : 负责创建类加载器。
SecurityClassLoad : 负责加载已经编译好的整个Server的class文件。
CatalinaProperties: 作为属性加载器,读取整个Server的系统属性,也读取同包中的Catalina.Properties的属性。
可以看出,Bootstrap类启动的方式可以说就是创建类加载器,加载Server 的class文件。
-----------------------------------------------------------------------
二、具体实现
首先是-----------Variables----------
1 public final class Bootstrap { 2 3 private static final Log log = LogFactory.getLog(Bootstrap.class); 4 private static Bootstrap daemon = null;
//文件路径 5 private static final File catalinaBaseFile; 6 private static final File catalinaHomeFile; 7 private static final Pattern PATH_PATTERN = Pattern.compile("(\".*?\")|(([^,])*)"); 8 private Object catalinaDaemon = null;
//类加载器 9 ClassLoader commonLoader = null; 10 ClassLoader catalinaLoader = null; 11 ClassLoader sharedLoader = null;
静态语句块static{...}对常量catalinaBaseFile,catalinaHomeFile进行了赋值操作。
1 static { 2 String userDir = System.getProperty("user.dir"); userDir="D:\IdeaProject\tomcatmini" 3 String home = System.getProperty("catalina.home"); home=null 4 File homeFile = null; 5 File f; 6 if (home != null) { 7 f = new File(home); 8 9 try { 10 homeFile = f.getCanonicalFile(); 11 } catch (IOException var9) { 12 homeFile = f.getAbsoluteFile(); 13 } 14 } 15 16 File baseFile; 17 if (homeFile == null) { homeFile = null 18 f = new File(userDir, "bootstrap.jar"); 19 if (f.exists()) { 20 baseFile = new File(userDir, ".."); 21 22 try { 23 homeFile = baseFile.getCanonicalFile(); 24 } catch (IOException var8) { 25 homeFile = baseFile.getAbsoluteFile(); 26 } 27 } 28 } 29 30 if (homeFile == null) { homeFile = null进入此分支, 31 f = new File(userDir); 32 33 try { 34 homeFile = f.getCanonicalFile(); 35 } catch (IOException var7) { 36 homeFile = f.getAbsoluteFile(); homeFile = "D:\IdeaProject\tomcatmini" 37 } 38 } 39 40 catalinaHomeFile = homeFile; 41 System.setProperty("catalina.home", catalinaHomeFile.getPath()); 42 String base = System.getProperty("catalina.base"); base = null 43 if (base == null) { 44 catalinaBaseFile = catalinaHomeFile; catalinaBaseFile = "D:\IdeaProject\tomcatmini" 45 } else { 46 baseFile = new File(base); 47 48 try { 49 baseFile = baseFile.getCanonicalFile(); 50 } catch (IOException var6) { 51 baseFile = baseFile.getAbsoluteFile(); 52 } 53 54 catalinaBaseFile = baseFile; 55 } 56 57 System.setProperty("catalina.base", catalinaBaseFile.getPath()); 58 }
然后是-----------main()-----------
1 public static void main(String[] args) { 2 if (daemon == null) { daemon == null 3 Bootstrap bootstrap = new Bootstrap(); 4 5 try { 6 bootstrap.init(); 点此init可以超链接哦 7 } catch (Throwable var3) { 8 handleThrowable(var3); 9 var3.printStackTrace(); 10 return; 11 } 12 13 daemon = bootstrap; 14 } else { 15 Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); 16 } 17 18 try { 19 String command = "start"; 20 if (args.length > 0) { 21 command = args[args.length - 1]; 22 } 23 24 if (command.equals("startd")) { 25 args[args.length - 1] = "start"; 26 daemon.load(args); 27 daemon.start(); 28 } else if (command.equals("stopd")) { 29 args[args.length - 1] = "stop"; 30 daemon.stop(); 31 } else if (command.equals("start")) { 32 daemon.setAwait(true); 33 daemon.load(args); 34 daemon.start(); 35 } else if (command.equals("stop")) { 36 daemon.stopServer(args); 37 } else if (command.equals("configtest")) { 38 daemon.load(args); 39 if (null == daemon.getServer()) { 40 System.exit(1); 41 } 42 43 System.exit(0); 44 } else { 45 log.warn("Bootstrap: command \"" + command + "\" does not exist."); 46 } 47 } catch (Throwable var4) { 48 Throwable t = var4; 49 if (var4 instanceof InvocationTargetException && var4.getCause() != null) { 50 t = var4.getCause(); 51 } 52 53 handleThrowable(t); 54 t.printStackTrace(); 55 System.exit(1); 56 } 57 58 }
----------------------init()----------------------
public void init() throws Exception { 此方法内部创建类加载器和安全加载相关类文件还有设置setContextClassLoader this.initClassLoaders(); 初始化类加载器 Thread.currentThread().setContextClassLoader(this.catalinaLoader); 设置当前线程为ContextClassLoader SecurityClassLoad.securityClassLoad(this.catalinaLoader); catalinaLoader作为类加载器加载去加载catalina服务器core,session,util等文件。 if (log.isDebugEnabled()) { log.debug("Loading startup class"); } Class<?> startupClass = this.catalinaLoader.loadClass("startup.Catalina"); Object startupInstance = startupClass.newInstance(); if (log.isDebugEnabled()) { log.debug("Setting startup class properties"); } String methodName = "setParentClassLoader"; Class<?>[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")}; Object[] paramValues = new Object[]{this.sharedLoader}; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); this.catalinaDaemon = startupInstance; }
-----------initClassLoaders-------------
private void initClassLoaders() { try{ this.commonLoader = this.createClassLoader("common", (ClassLoader)null); if (this.commonLoader == null) { this.commonLoader = this.getClass().getClassLoader(); } this.catalinaLoader = this.createClassLoader("server", this.commonLoader); this.sharedLoader = this.createClassLoader("shared", this.commonLoader); } catch (Throwable var2) { handleThrowable(var2); log.error("Class loader creation threw exception", var2); System.exit(1); } }
-------
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception { String value = CatalinaProperties.getProperty(name + ".loader"); System.out.println(value); if (value != null && !value.equals("")) { value = this.replace(value); List<ClassLoaderFactory.Repository> repositories = new ArrayList(); String[] repositoryPaths = getPaths(value); String[] arr$ = repositoryPaths; int len$ = repositoryPaths.length; for(int i$ = 0; i$ < len$; ++i$) { String repository = arr$[i$]; try { new URL(repository); repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.URL)); } catch (MalformedURLException var11) { if (repository.endsWith("*.jar")) { repository = repository.substring(0, repository.length() - "*.jar".length()); repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.GLOB)); } else if (repository.endsWith(".jar")) { repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.JAR)); } else { repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.DIR)); } } } return ClassLoaderFactory.createClassLoader(repositories, parent); } else { return parent; } }
-----------------------