文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Tomcat9如何加载server.xml

2023-06-02 13:52

关注

小编给大家分享一下Tomcat9如何加载server.xml,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1.Tomcat启动

org.apache.catalina.startup.Bootstrap.main(String args[])
 public static void main(String args[]) {        synchronized (daemonLock) {            if (daemon == null) {                Bootstrap bootstrap = new Bootstrap();                try {                    bootstrap.init(); //初始化类加载器                } catch (Throwable t) {                    handleThrowable(t);                    t.printStackTrace();                    return;                }                daemon = bootstrap;            } else {                Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);            }        }        //根据传入的不同指令,进行相应处理        try {            String command = "start";            if (args.length > 0) {                command = args[args.length - 1];            }            if (command.equals("startd")) {                args[args.length - 1] = "start";                daemon.load(args);                daemon.start();            } else if (command.equals("stopd")) {                args[args.length - 1] = "stop";                daemon.stop();            } else if (command.equals("start")) {                daemon.setAwait(true);                daemon.load(args);                daemon.start();                if (null == daemon.getServer()) {                    System.exit(1);                }            } else if (command.equals("stop")) {                daemon.stopServer(args);            } else if (command.equals("configtest")) {                daemon.load(args);                if (null == daemon.getServer()) {                    System.exit(1);                }                System.exit(0);            } else {                log.warn("Bootstrap: command \"" + command + "\" does not exist.");            }        } catch (Throwable t) {            if (t instanceof InvocationTargetException &&                    t.getCause() != null) {                t = t.getCause();            }            handleThrowable(t);            t.printStackTrace();            System.exit(1);        }    }

在main方法中主要为两部分逻辑:

org.apache.catalina.startup.Bootstrap.init()
 public void init() throws Exception {        initClassLoaders(); //初始化类加载        Thread.currentThread().setContextClassLoader(catalinaLoader); //设置当前线程的类加载器为catalinaLoader        SecurityClassLoad.securityClassLoad(catalinaLoader); //启用java安全管理的处理        //通过反射的方式实例化org.apache.catalina.startup.Catalina,并设置父类加载器为sharedLoader        if (log.isDebugEnabled())            log.debug("Loading startup class");        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");        Object startupInstance = startupClass.getConstructor().newInstance();        if (log.isDebugEnabled())            log.debug("Setting startup class properties");        String methodName = "setParentClassLoader";        Class<?> paramTypes[] = new Class[1];        paramTypes[0] = Class.forName("java.lang.ClassLoader");        Object paramValues[] = new Object[1];        paramValues[0] = sharedLoader;        Method method =            startupInstance.getClass().getMethod(methodName, paramTypes);        method.invoke(startupInstance, paramValues);        catalinaDaemon = startupInstance;    }
org.apache.catalina.security.SecurityClassLoad
public final class SecurityClassLoad {    public static void securityClassLoad(ClassLoader loader) throws Exception {        securityClassLoad(loader, true);    }    static void securityClassLoad(ClassLoader loader, boolean requireSecurityManager) throws Exception {        if (requireSecurityManager && System.getSecurityManager() == null) {            return;        }        loadCorePackage(loader);        loadCoyotePackage(loader);        loadLoaderPackage(loader);        loadRealmPackage(loader);        loadServletsPackage(loader);        loadSessionPackage(loader);        loadUtilPackage(loader);        loadJavaxPackage(loader);        loadConnectorPackage(loader);        loadTomcatPackage(loader);    }

当时使用Java SecurityManager时,会提前加载一些必要的java类,以避免触发权限异常AccessControlException

2.server.xml解析框架

2.1 SAX

Tomcat中使用SAX解析server.xml文件。SAX解析方式会逐行的解析XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML,它的优点是不需要将完整的XML文档加载进内存,可以在读取文档的同时就进行解析,节省内存,适合解析超大XML,主要方法有:

2.2 规则Rules

Tomcat9如何加载server.xml
Tomcat将server.xml的解析抽象为规则,利用Java的引用传递,通过有副作用的void方法,对xml进行解析,规则调用的顺序与xml解析的顺序是一致的,即start方法是正序,end方法是逆序。
规则中包含以下方法:

Tomcat中常见的规则类型:

3.server.xml解析源代码解析

org.apache.catalina.startup.Catalina.load()
public void load() {        if (loaded) {            return;        }        loaded = true;        long t1 = System.nanoTime();        initDirs();        // Before digester - it may be needed        initNaming();        // 读取conf/server.xml        ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(Bootstrap.getCatalinaBaseFile(), getConfigFile()));        File file = configFile();        // 创建xml解析Digester         Digester digester = createStartDigester();        try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()) {            InputStream inputStream = resource.getInputStream();            InputSource inputSource = new InputSource(resource.getURI().toURL().toString());            inputSource.setByteStream(inputStream);            digester.push(this);            digester.parse(inputSource); //解析xml        } catch (Exception e) {            log.warn(sm.getString("catalina.configFail", file.getAbsolutePath()), e);            if (file.exists() && !file.canRead()) {                log.warn(sm.getString("catalina.incorrectPermissions"));            }            return;        }        //设置server的属性        getServer().setCatalina(this);        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());        // Stream redirection        initStreams();        // 初始化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(sm.getString("catalina.initError"), e);            }        }        long t2 = System.nanoTime();        if(log.isInfoEnabled()) {            log.info(sm.getString("catalina.init", Long.valueOf((t2 - t1) / 1000000)));        }    }
org.apache.catalina.startup.Catalina.createStartDigester()
 protected Digester createStartDigester() {        long t1=System.currentTimeMillis();        // Initialize the digester        Digester digester = new Digester();        digester.setValidating(false);        digester.setRulesValidation(true);        Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();        // Ignore className on all elements        List<String> objectAttrs = new ArrayList<>();        objectAttrs.add("className");        fakeAttributes.put(Object.class, objectAttrs);        // Ignore attribute added by Eclipse for its internal tracking        List<String> contextAttrs = new ArrayList<>();        contextAttrs.add("source");        fakeAttributes.put(StandardContext.class, contextAttrs);        // Ignore Connector attribute used internally but set on Server        List<String> connectorAttrs = new ArrayList<>();        connectorAttrs.add("portOffset");        fakeAttributes.put(Connector.class, connectorAttrs);        digester.setFakeAttributes(fakeAttributes);        digester.setUseContextClassLoader(true);        // Configure the actions we will be using        digester.addObjectCreate("Server",                                 "org.apache.catalina.core.StandardServer",                                 "className");        digester.addSetProperties("Server");        digester.addSetNext("Server",                            "setServer",                            "org.apache.catalina.Server");        digester.addObjectCreate("Server/GlobalNamingResources",                                 "org.apache.catalina.deploy.NamingResourcesImpl");        digester.addSetProperties("Server/GlobalNamingResources");        digester.addSetNext("Server/GlobalNamingResources",                            "setGlobalNamingResources",                            "org.apache.catalina.deploy.NamingResourcesImpl");        digester.addRule("Server/Listener",                new ListenerCreateRule(null, "className"));        digester.addSetProperties("Server/Listener");        digester.addSetNext("Server/Listener",                            "addLifecycleListener",                            "org.apache.catalina.LifecycleListener");        digester.addObjectCreate("Server/Service",                                 "org.apache.catalina.core.StandardService",                                 "className");        digester.addSetProperties("Server/Service");        digester.addSetNext("Server/Service",                            "addService",                            "org.apache.catalina.Service");        digester.addObjectCreate("Server/Service/Listener",                                 null, // MUST be specified in the element                                 "className");        digester.addSetProperties("Server/Service/Listener");        digester.addSetNext("Server/Service/Listener",                            "addLifecycleListener",                            "org.apache.catalina.LifecycleListener");        //Executor        digester.addObjectCreate("Server/Service/Executor",                         "org.apache.catalina.core.StandardThreadExecutor",                         "className");        digester.addSetProperties("Server/Service/Executor");        digester.addSetNext("Server/Service/Executor",                            "addExecutor",                            "org.apache.catalina.Executor");        digester.addRule("Server/Service/Connector",                         new ConnectorCreateRule());        digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(                new String[]{"executor", "sslImplementationName", "protocol"}));        digester.addSetNext("Server/Service/Connector",                            "addConnector",                            "org.apache.catalina.connector.Connector");        digester.addRule("Server/Service/Connector", new AddPortOffsetRule());        digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",                                 "org.apache.tomcat.util.net.SSLHostConfig");        digester.addSetProperties("Server/Service/Connector/SSLHostConfig");        digester.addSetNext("Server/Service/Connector/SSLHostConfig",                "addSslHostConfig",                "org.apache.tomcat.util.net.SSLHostConfig");        digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",                         new CertificateCreateRule());        digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",                         new SetAllPropertiesRule(new String[]{"type"}));        digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",                            "addCertificate",                            "org.apache.tomcat.util.net.SSLHostConfigCertificate");        digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",                                 "org.apache.tomcat.util.net.openssl.OpenSSLConf");        digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");        digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",                            "setOpenSslConf",                            "org.apache.tomcat.util.net.openssl.OpenSSLConf");        digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",                                 "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");        digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");        digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",                            "addCmd",                            "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");        digester.addObjectCreate("Server/Service/Connector/Listener",                                 null, // MUST be specified in the element                                 "className");        digester.addSetProperties("Server/Service/Connector/Listener");        digester.addSetNext("Server/Service/Connector/Listener",                            "addLifecycleListener",                            "org.apache.catalina.LifecycleListener");        digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",                                  null, // MUST be specified in the element                                  "className");        digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");        digester.addSetNext("Server/Service/Connector/UpgradeProtocol",                            "addUpgradeProtocol",                            "org.apache.coyote.UpgradeProtocol");        // Add RuleSets for nested elements        digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));        digester.addRuleSet(new EngineRuleSet("Server/Service/"));        digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));        digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));        addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");        digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));        // When the 'engine' is found, set the parentClassLoader.        digester.addRule("Server/Service/Engine",                         new SetParentClassLoaderRule(parentClassLoader));        addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");        long t2=System.currentTimeMillis();        if (log.isDebugEnabled()) {            log.debug("Digester for server.xml created " + ( t2-t1 ));        }        return digester;    }

此方法创建解析server.xml的Digester,根据server.xml的元素标签,为每个标签设置相应的规则组,在解析标签时进行调用。
由此也可以得到结论,server.xml的结构就是Tomcat容器内部的结构,通过对server.xml的解析规则的执行,实例化出Tomcat容器结构。

以下为Tomcat9默认的server.xml

<?xml version="1.0" encoding="UTF-8"?><Server port="8005" shutdown="SHUTDOWN">  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />  <GlobalNamingResources>    <Resource name="UserDatabase" auth="Container"              type="org.apache.catalina.UserDatabase"              description="User database that can be updated and saved"              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"              pathname="conf/tomcat-users.xml" />  </GlobalNamingResources>  <Service name="Catalina">    <Connector port="8080" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" />    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />    <Engine name="Catalina" defaultHost="localhost">      <Realm className="org.apache.catalina.realm.LockOutRealm">        <!-- This Realm uses the UserDatabase configured in the global JNDI             resources under the key "UserDatabase".  Any edits             that are performed against this UserDatabase are immediately             available for use by the Realm.  -->        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"               resourceName="UserDatabase"/>      </Realm>      <Host name="localhost"  appBase="webapps"            unpackWARs="true" autoDeploy="true">        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"               prefix="localhost_access_log" suffix=".txt"               pattern="%h %l %u %t "%r" %s %b" />      </Host>    </Engine>  </Service></Server>

其结构见下图:
Tomcat9如何加载server.xml

以上是“Tomcat9如何加载server.xml”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯