Tomcat9如何加載server.xml

蝸牛 互聯網技術資訊 2021-12-08 174 0

小編給大家分享一下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方法中主要為兩部分邏輯:

  • 調用bootstrap.init()進行初始化

  • 根據傳入不同的指令進行相應的處理,本文主要分析start指定,即服務啟動。啟動服務start主要調用了org.apache.catalina.startup.Catalina.load()和start()方法

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;
????}
  • 類加載器的初始化,創建commonLoader、catalinaLoader、sharedLoader,具體可參考上一篇 《Tomcat9源代碼淺析-類加載體系》

  • 啟用java安全管理的處理

  • 通過反射的方式實例化org.apache.catalina.startup.Catalina,并設置父類加載器為sharedLoader

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,主要方法有:

  • startDocument():文檔解析開始時調用,該方法只會調用一次

  • startElement(String uri, String localName, String qName, Attributes attributes):標簽解析開始時調用

  • endElement(String uri, String localName, String qName):標簽(節點)解析結束后調用

  • endDocument():文檔解析結束后調用,該方法只會調用一次

2.2 規則Rules

Tomcat9如何加載server.xml  tomcat9 第1張
Tomcat將server.xml的解析抽象為規則,利用Java的引用傳遞,通過有副作用的void方法,對xml進行解析,規則調用的順序與xml解析的順序是一致的,即start方法是正序,end方法是逆序。
規則中包含以下方法:

  • begin:Degister.startElement 方法調用

  • body、end:Degister.endElement方法中調用,先調用body,再調用end

  • finish:Degister.endDocument方法中調用

Tomcat中常見的規則類型:

  • ObjectCreateRule 創建對應class的對象實例,并放到Designer的堆棧成員屬性中

  • SetPropertiesRule 獲取堆棧中棧頂的元素,并將xml元素的屬性賦值給對象實例

  • SetNextRule 調用父節點的實例對象,將當前對象作為參數,反射調用某個方法

  • ListenerCreateRule 當Listener標簽有optional屬性為true時,創建實例異常時,強制添加OptionalListener實例

  • ConnectorCreateRule 創建Connector實例

  • SetAllPropertiesRule 主體功能與SetPropertiesRule 一致,這個Rule可以排除一些屬性的設置

  • AddPortOffsetRule Set portOffset on all the connectors based on portOffset in the Server

  • CertificateCreateRule 實例化SSLHostConfigCertificate

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)));
????????}
????}
  • Bootstrap中start指令邏輯,通過反射調用Catalina.load()

  • Catalina.load() 讀取conf/server.xml,創建解析xml的Digester

  • 開始初始化server

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 第2張

  • Server代表服務器,一個Tomcat只有一個Server

  • Service 代表服務: 一個Server可以對外提供多個服務

  • Connector連接器: service服務的核心組成之一,主要是鏈接客戶端請求

  • Container容器:service服務的核心組成之一,主要是執行業務邏輯,這里按層級為Engine、Host、Context

  • Wrapper:對應Servlet的定義
    Tomcat9如何加載server.xml  tomcat9 第3張

以上是“Tomcat9如何加載server.xml”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注蝸牛博客行業資訊頻道!

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:niceseo99@gmail.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

評論

2018人人澡人摸人人添_月夜影视在线观看资源_一本二卡三卡四卡乱码小说_tobu8在线观看下载