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


    前言

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

    源码分析

      Bootstrap的load方法是加载tomcat的server.xml的入口,load方法实际通过反射调用了Catalina的load方法,见代码清单1。

    代码清单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 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");
    
    }

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

    总结

      从上面的分析可以看到,tomcat加载server.xml配置文件的方式,非常传统,正是使用FileInputStream进行加载的。有关server.xml配置文件的解析会在之后补充。

    如需转载,请标明本文作者及出处——作者:jiaan.gja,本文原创首发:博客园,原文链接:http://www.cnblogs.com/jiaan-geng/p/4863154.html 
  • 相关阅读:
    android:重写返回键动画
    获得今天零点时间戳(转)
    【转】完美解决Android 9.0以上HTTP网络请求被限制问题
    Java的三种取整方法
    thymeleaf控制checkbox的选中状态回显
    thymeleaf控制checkbox的value值
    Supervisor 简单使用
    关于Requests代理,你必须知道的
    py-spy 常见问题及使用说明
    记一次Scrapy进程卡死的Debug过程
  • 原文地址:https://www.cnblogs.com/jiaan-geng/p/4863154.html
Copyright © 2020-2023  润新知