深入Tomcat(一)
java不难,难的是那些封装好的框架和工具,由于我们对这些工具没有深入的了解,所以在开发时经常是东查西凑,也就不难想到成果物的质量。所以决定从现在开始阅读Tomcat代码。每天一点点,坚持就是胜利。????
版本:6.0.18?
启动类:org.apache.catalina.startup包下的Bootstrap,下面是main方法:
??? 首先创建启动类的实例,调用init方法:
每一个Tomcat实例都有自己的工作目录,它们共享一个安装目录。
bin,lib这两个文件夹是共享的,存放安装文件和lib库。
conf,logs,temp,work,webapps这几个目录是每个Tomcat实例私有的,我们只需要拷贝这几个目录就能实现运行多个实例的目的。现在我对文件夹进行了改造:
?
新建两个工作目录Tomcat 6.0_1和Tomcat 6.0_2,将conf,logs,temp,work,webapps这五个文件夹分别拷贝到这两个工作目录下,为了更好的区分安装目录与工作目录,我将原始的安装目录下除了bin和lib文件夹以外全部删除。这样每个实例的工作目录就配好了。接下来需要配置Tomcat实例运行需要的资源---端口号,我修改了每个实例下面的server.xml。将shutdown端口号,还有http监听端口号,ajp端口号全部修改,我这里把监听http端口号设置成8080,另一个设置成8888。最后就是启动了。我用的是安装版本,不是启动bat文件的。
双击安装目录下的tomcat6w.exe,点击java选项卡,修改-Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 6.0_1,点击应用,确定,双击tomcat6.exe,启动第一个实例。
?
再双击安装目录下的tomcat6w.exe,点击java选项卡,修改-Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 6.0_2,点击应用,确定,双击tomcat6.exe,启动第二个实例。
如果是用startup.bat文件启动,同样修改CATALINA_BASE指向的工作目录即可。
?
说完了安装目录和工作目录的作用和区别。我们来看看setCatalinaHome方法。
???
下面是CatalinaProperties类,负责读取catalina.properties 文件。
?
public class CatalinaProperties { // ------------------------------------------------------- Static Variables private static org.apache.juli.logging.Log log= org.apache.juli.logging.LogFactory.getLog( CatalinaProperties.class ); private static Properties properties = null; static { loadProperties(); } /** * Return specified property value. */ public static String getProperty(String name) { return properties.getProperty(name); } /** * Return specified property value. */ public static String getProperty(String name, String defaultValue) { return properties.getProperty(name, defaultValue); } /** * Load properties. */ private static void loadProperties() { InputStream is = null; Throwable error = null; try { String configUrl = getConfigUrl(); if (configUrl != null) { is = (new URL(configUrl)).openStream(); } } catch (Throwable t) { // Ignore } if (is == null) { try { File home = new File(getCatalinaBase()); File conf = new File(home, "conf"); File properties = new File(conf, "catalina.properties"); is = new FileInputStream(properties); } catch (Throwable t) { // Ignore } } if (is == null) { try { is = CatalinaProperties.class.getResourceAsStream ("/org/apache/catalina/startup/catalina.properties"); } catch (Throwable t) { // Ignore } } if (is != null) { try { properties = new Properties(); properties.load(is); is.close(); } catch (Throwable t) { error = t; } } if ((is == null) || (error != null)) { // Do something log.warn("Failed to load catalina.properties", error); // That's fine - we have reasonable defaults. properties=new Properties(); } // Register the properties as system properties Enumeration enumeration = properties.propertyNames(); while (enumeration.hasMoreElements()) { String name = (String) enumeration.nextElement(); String value = properties.getProperty(name); if (value != null) { System.setProperty(name, value); } } } /** * Get the value of the catalina.home environment variable. */ private static String getCatalinaHome() { return System.getProperty("catalina.home", System.getProperty("user.dir")); } /** * Get the value of the catalina.base environment variable. */ private static String getCatalinaBase() { return System.getProperty("catalina.base", getCatalinaHome()); } /** * Get the value of the configuration URL. */ private static String getConfigUrl() { return System.getProperty("catalina.config"); }}?
?首先从系统属性catalina.config中寻找,如果没有此文件,则从Tomcat的工作目录下的conf中寻找该文件(存在该文件)。如果仍然没有此文件则从/org/apache/catalina/startup包中寻找catalina.properties文件。说一下getResourceAsStream()的用法,由于“/org/apache/catalina/startup”字符串使用“/”开始的,“/”代表根目录,根目录是以类文件(class文件)package的顶层目录为基准,寻找资源文件的。比如在Web应用中,有一个WEB-INF的目录,WEB-INF目录里面除了web.xml文件外,还有一个classes目录,没错了,它就是你这个WEB应用的package的顶层目录。如果不是以“/”开始,则是相对于该类文件所在目录的相对路径寻找的。
找到catalina.properties文件后, 创建Properties类的实例,装载该文件流。之后将从属性文件中读取到的属性设置在系统属性中。
回退到createClassLoader方法中,传入的参数为“common”和null,查阅Tomcat安装目录下conf文件夹中的catalina.properties文件,可知common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jar,得到的locations{"D://xxxx//bin//lib", "D://xxxx//bin//lib//"},得到的types{ClassLoaderFactory.IS_DIR, ClassLoaderFactory.IS_GLOB}。
ClassLoaderFactory类