Tomcat源码分析——server.xml文件的加载

简介:

前言

作为Java程序员,对于tomcat的server.xml想必都不陌生。本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载的进行分析。

源码分析

Bootstrap的load方法用于加载tomcat的server.xml,实际是通过反射调用Catalina的load方法,代码如下:

/**
 * 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方法实现如下:

/**
 * 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 xml, just create it manually.
    if( inputStream==null ) {
        try {
            inputStream = getClass().getClassLoader()
            .getResourceAsStream("server-embed.xml");
            inputSource = new InputSource
            (getClass().getClassLoader()
                    .getResource("server-embed.xml").toString());
        } catch (Exception e) {
            // Ignore
        }
    }


    if ((inputStream == null) && (file != null)) {
        log.warn("Can't load server.xml from " + 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");

}

这里对上述代码进行分析:
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.xml。
4) 使用FileInputStream获取conf/server.xml配置文件输入流。
5) 将FileInputStream封装为InputSource,并且调用Digester的parse方法进行解析。
6) initStreams对输出流、错误流重定向。
7) 初始化server,具体实现本文不做分析。

相关文章
|
5月前
|
缓存 JavaScript 应用服务中间件
Nginx+Tomcat代理环境下JS无法完全加载问题
Nginx+Tomcat代理环境下JS无法完全加载问题
|
1月前
|
Java 应用服务中间件
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
132 1
|
8月前
|
SQL 关系型数据库 MySQL
CentOS部署JAVA程序、安装Tomcat以及安装导入mysql文件的方法
CentOS部署JAVA程序、安装Tomcat以及安装导入mysql文件的方法
|
4月前
|
XML Java 应用服务中间件
Tomcat服务器Server.xml详解
Tomcat服务器Server.xml详解
|
5月前
|
Unix 应用服务中间件 Linux
Tomcat清理日志文件无法立即释放磁盘空间
Tomcat清理日志文件无法立即释放磁盘空间
|
6月前
|
XML JavaScript 前端开发
12jqGrid - 加载XML数据
12jqGrid - 加载XML数据
18 0
|
6月前
|
XML JSON JavaScript
SAP Fiori Elements 应用里标准模板 XML Fragment 加载的逻辑和 XMLPreprocessor 的作用
SAP Fiori Elements 应用里标准模板 XML Fragment 加载的逻辑和 XMLPreprocessor 的作用
52 0
|
10月前
|
XML Java 数据格式
Spring源码深度解析01-debug式看如何加载xml配置文件
Spring源码深度解析01-debug式看如何加载xml配置文件
122 0
|
10月前
|
Java 应用服务中间件
用IDEA创建servlet文件并用Tomcat运行
用IDEA创建servlet文件并用Tomcat运行
133 0
|
Java 应用服务中间件 Apache
都2020了你该知道Tomcat真正的启动文件了
都2020了你该知道Tomcat真正的启动文件了
278 0
都2020了你该知道Tomcat真正的启动文件了