你的位置:首页 > Java教程

[Java教程]Tomcat源码分析——server.xml文件的加载


前言

  作为Java程序员,对于tomcat的server.

源码分析

  Bootstrap的load方法是加载tomcat的server.

代码清单1

/** * Load daemon. */private void load(String[] arguments)  throws Exception {  // Call the load() method  String methodName = "load";  Object param[];  Class<?> paramTypes[];  if (arguments==null || arguments.length==0) {    paramTypes = null;    param = null;  } else {    paramTypes = new Class[1];    paramTypes[0] = arguments.getClass();    param = new Object[1];    param[0] = arguments;  }  Method method =     catalinaDaemon.getClass().getMethod(methodName, paramTypes);  if (log.isDebugEnabled())    log.debug("Calling startup class " + method);  method.invoke(catalinaDaemon, param);}

Catalina的load方法的实现见代码清单2。

代码清单2

/** * Start a new server instance. */public void load() {  long t1 = System.nanoTime();  initDirs();  // Before digester - it may be needed  initNaming();  // Create and execute our Digester  Digester digester = createStartDigester();  InputSource inputSource = null;  InputStream inputStream = null;  File file = null;  try {    file = configFile();    inputStream = new FileInputStream(file);    inputSource = new InputSource("file://" + file.getAbsolutePath());  } catch (Exception e) {    // Ignore  }  if (inputStream == null) {    try {      inputStream = getClass().getClassLoader()        .getResourceAsStream(getConfigFile());      inputSource = new InputSource        (getClass().getClassLoader()         .getResource(getConfigFile()).toString());    } catch (Exception e) {      // Ignore    }  }  // This should be included in catalina.jar  // Alternative: don't bother with   if( inputStream==null ) {    try {      inputStream = getClass().getClassLoader()      .getResourceAsStream("server-embed.);      inputSource = new InputSource      (getClass().getClassLoader()          .getResource("server-embed.).toString());    } catch (Exception e) {      // Ignore    }  }  if ((inputStream == null) && (file != null)) {    log.warn("Can't load server. file.getAbsolutePath());    if (file.exists() && !file.canRead()) {      log.warn("Permissions incorrect, read permission is not allowed on the file.");    }    return;  }  try {    inputSource.setByteStream(inputStream);    digester.push(this);    digester.parse(inputSource);    inputStream.close();  } catch (Exception e) {    log.warn("Catalina.start using "              + getConfigFile() + ": " , e);    return;  }  // Stream redirection  initStreams();  // Start the new server  try {    getServer().init();  } catch (LifecycleException e) {    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))      throw new java.lang.Error(e);    else        log.error("Catalina.start", e);  }  long t2 = System.nanoTime();  if(log.isInfoEnabled())    log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");}

这里对代明清单2进行分析,其执行步骤如下:
1) initDirs方法用于对catalina.home和catalina.base的一些检查工作。
2) initNaming方法给系统设置java.naming.factory.url.pkgs和java.naming.factory.initial。在创建JNDI上下文时,使用Context.INITIAL_CONTEXT_FACTORY("java.naming.factory.initial")属性,来指定创建JNDI上下文的工厂类;Context.URL_PKG_PREFIXES("java.naming.factory.url.pkgs")用在查询url中包括scheme方法id时创建对应的JNDI上下文,例如查询"java:/jdbc/test1"等类似查询上,即以冒号":"标识的shceme。Context.URL_PKG_PREFIXES属性值有多个java 包(package)路径,其中以冒号":"分隔各个包路径,这些包路径中包括JNDI相关实现类。当在JNDI上下文中查找"java:"这类包括scheme方案ID的url时,InitialContext类将优先查找Context.URL_PKG_PREFIXES属性指定的包路径中是否存在 scheme+"."+scheme + "URLContextFactory"工厂类(需要实现ObjectFactory接口),如果存在此工厂类,则调用此工厂类的getObjectInstance方法获得此scheme方案ID对应的jndi上下文,再在此上下文中继续查找对应的url。
3) createStartDigester方法创建并配置将要用来启动的Digester实例,并且设置一系列Rule,具体映射到server.
4) 使用FileInputStream获取conf/server.
5) 将FileInputStream封装为InputSource,并且调用Digester的parse方法进行解析。
6) initStreams对输出流、错误流重定向。
7) 初始化server,具体实现本文不做分析。

总结

  从上面的分析可以看到,tomcat加载server.