中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Tomcat的啟動過程是怎樣的

發布時間:2021-12-24 17:36:38 來源:億速云 閱讀:142 作者:iii 欄目:服務器

本篇內容主要講解“Tomcat的啟動過程是怎樣的”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Tomcat的啟動過程是怎樣的”吧!

1.Tomcat分析

阿粉知道作為一個 Java 資深開發人員,對 Tomcat  那是再熟悉不過了,bin目錄、conf目錄、webapps目錄,對這些目錄熟悉的簡直不能再熟悉了。一言不合就是一個shutdown.sh,或者來個shutdown.bat,但是你知道你的啟動startup.bat,和startup.sh他們的啟動過程是什么過程么?接下來我們就開始進入分析吧。

2.Tomcat的整體結構圖

這個整體結構圖可不是大家想的目錄結構圖,目錄結構圖阿粉就不給大家展示了,自己去打開你的  Tomcat,里面就有你想看到目錄結構圖,那么整體結構圖是什么樣子的呢?

Tomcat的啟動過程是怎樣的

給大家解釋一下這個圖的意思,

  • Server:整個服務器

  • Service:具體的服務。

  • Connector:提供Socket和request,response的連接。

  • Container:用于封裝和管理Servlet,以及具體的處理請求。

這個圖就把里面的包含關系說的是明明白白了,為什么這么說呢?因為一個Server中可以存在多個服務,也就是多個Service,而一個Service中可以存在多個Connector,但是只能存在一個Container,是不是就非常的清晰了呢?

3.Tomcat的啟動過程

接下來我們就來看看源碼里面的啟動過程吧,Bootstrap類中的啟動過程。

這個類的位置是在tomcat的catalina的包里面,大家看一下主方法也就是所謂的main方法,

public static void main(String[] args) {       //對象初始化       if (daemon == null) {           Bootstrap bootstrap = new Bootstrap();            try {               bootstrap.init();           } catch (Throwable var3) {               handleThrowable(var3);               var3.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 var4) {           Throwable t = var4;           if (var4 instanceof InvocationTargetException && var4.getCause() != null) {               t = var4.getCause();           }            handleThrowable(t);           t.printStackTrace();           System.exit(1);       }    }

main方法里面的存在也很簡單,先進行init的操作,然后再執行start,也就是說,啟動過程中,首先要進行初始化,然后接下來再進行啟動,最后階段在來個stop,這樣才算完整嘛。

  • load方法:其實說白了load方法就是根據server.xml文件創建Server并且調用Server的init方法進行初始化。

  • start方法:start方法很直白,啟動服務器。

  • stop方法:stop方法同樣,停止服務器。

在這里的start方法和stop方法調用的分別就是調用了Server內部的start和stop方法,而這三個方法都是按照圖中的層級結構來的,先從Server的load,start,stop,然后Server的start再調用Service的start,而Service的start調用的就是Connector和Container的start方法了,這從外到內的啟動,就可以把Tomcat完整的啟動起來了。

我們在接下來就繼續從外到內的啟動開始分析一波。

3.1 Catalina啟動過程

上面的啟動入口我們已經成功找到了,那么我們就繼續來,對象初始化完成后,執行了init的方法

Bootstrap bootstrap = new Bootstrap();             try {                bootstrap.init();            } catch (Throwable var3) {

就是上面的這個,如果參數為空了,那么就開始調用start了,那么start方法是什么呢?

public void start() throws Exception {        if (this.catalinaDaemon == null) {            this.init();        }         Method method = this.catalinaDaemon.getClass().getMethod("start", (Class[])null);        method.invoke(this.catalinaDaemon, (Object[])null);    }

上面的start方法就是直接使用invoke的方法映射到了catalinaDaemon,也就是到了Catalina的start的方法上,

而這個Catalina的啟動無非也就是調用了同樣的方法,setAwait方法,load方法,start方法,

  • setAwait方法:用于設置Server啟動完成時,是否進入等待,如果是true,那就等待,如果不是false,那就不進入等待。

  • load方法:創建并且初始化Server,

  • start方法:同樣是啟動服務器

同樣的setAwait方法比較少,阿粉就不給大家看了,無非就是個判斷,而load方法一定得看,

if (!this.loaded) {             this.loaded = true;             long t1 = System.nanoTime();                     try {                         inputSource.setByteStream((InputStream)inputStream);                         digester.push(this);                         digester.parse(inputSource);                         break label242;                     } catch (SAXParseException var28) {                         log.warn("Catalina.start using " + this.getConfigFile() + ": " + var28.getMessage());                         return;                     } catch (Exception var29) {                         log.warn("Catalina.start using " + this.getConfigFile() + ": ", var29);                     }                 } finally {                     if (inputStream != null) {                         try {                             ((InputStream)inputStream).close();                         } catch (IOException var23) {                             ;                         }                     }                  }                  return;             }  try {     //此處同樣調用的Server的init方法,                 this.getServer().init();             } catch (LifecycleException var24) {                 if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {                     throw new Error(var24);                 }                  log.error("Catalina.start", var24);             }              long t2 = System.nanoTime();             if (log.isInfoEnabled()) {                 log.info("Initialization processed in " + (t2 - t1) / 1000000L + " ms");             }          }

而從這里就開始進入下一步了,Server的啟動過程,因為從Catalina里面已經找到了getServer的初始化方法,接下來就是要進行Server的初始化,然后加載,然后啟動的過程了。

3.2 Server的啟動過程

Server是Tomcat里面的接口,而不是類,那么我們就只能去找實現它的子類來于是就找到了StandardServer  extends LifecycleMBeanBase implements Server。

阿粉一看有繼承,還有實現,那就先看看LifecycleMBeanBase這個被繼承的類,于是再次去看了它,

public abstract class LifecycleMBeanBase extends LifecycleBase implements JmxEnabled {

嗯?還有繼承?繼續往下扒拉,

public abstract class LifecycleBase implements Lifecycle {

終于算是找到了,

Tomcat的啟動過程是怎樣的

Tomcat的啟動過程是怎樣的

阿粉一看這init方法和start方法又調用了initInternal()和startInternal(),找來找去又回去了,而阿粉也從這里知道了,模板方法,是有自己的子類具體實現

于是回到了StandardServer自己的init和start方法,

protected void startInternal() throws LifecycleException {        this.fireLifecycleEvent("configure_start", (Object)null);        this.setState(LifecycleState.STARTING);        this.globalNamingResources.start();        Object var1 = this.servicesLock;        synchronized(this.servicesLock) {            for(int i = 0; i < this.services.length; ++i) {                this.services[i].start();            }         }    }

Tomcat的啟動過程是怎樣的

總得來說就是,StandardServer繼承自LifecycleMBeanBase,而LifecycleMBeanBase繼承自LifecycleBase,而LifecycleBase類中的模板方法,又讓自己的子類去進行具體的實現,但是我們要知道他的Tomcat生命周期中存在這些內容才行。

圖中都說了,Server里面有Service,那么一定就有,我們得去找找看,于是阿粉再次去找并且去看它到底是個什么意思,

public void addService(Service service) {         service.setServer(this);         Object var2 = this.servicesLock;         synchronized(this.servicesLock) {             Service[] results = new Service[this.services.length + 1];             System.arraycopy(this.services, 0, results, 0, this.services.length);             results[this.services.length] = service;             this.services = results;             if (this.getState().isAvailable()) {                 try {                     service.start();                 } catch (LifecycleException var6) {                     ;                 }             }              this.support.firePropertyChange("service", (Object)null, service);         }     }

位置是在Server的接口中出現了增加和刪除Service的方法,Server的init方法和start方法循環去調用每個Service的init方法和start方法。

接下來我們看看Service的具體實現,找到StandardService:

protected void initInternal() throws LifecycleException {        super.initInternal();        if (this.engine != null) {            this.engine.init();        }         Executor[] arr$ = this.findExecutors();        int len$ = arr$.length;         int len$;        for(len$ = 0; len$ < len$; ++len$) {            Executor executor = arr$[len$];            if (executor instanceof JmxEnabled) {                ((JmxEnabled)executor).setDomain(this.getDomain());            }             executor.init();        }         this.mapperListener.init();        Object var11 = this.connectorsLock;        synchronized(this.connectorsLock) {            Connector[] arr$ = this.connectors;            len$ = arr$.length;             for(int i$ = 0; i$ < len$; ++i$) {                Connector connector = arr$[i$];                 try {                    connector.init();                } catch (Exception var9) {                    String message = sm.getString("standardService.connector.initFailed", new Object[]{connector});                    log.error(message, var9);                    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {                        throw new LifecycleException(message);                    }                }            }         }    }

而在方法中主要調用Executor,mapperListener,executor的init方法。

connector之前已經有了,而這個mapperListener就是Mapper的監聽器,用來堅挺container容器的變化。


Tomcat的啟動過程是怎樣的

到此,相信大家對“Tomcat的啟動過程是怎樣的”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

德州市| 黄大仙区| 安塞县| 石河子市| 巨鹿县| 德格县| 邵阳县| 抚顺市| 洛川县| 介休市| 舞阳县| 四平市| 宜春市| 剑河县| 迭部县| 陵水| 敦化市| 高邑县| 南平市| 巢湖市| 鱼台县| 启东市| 溧水县| 浑源县| 景泰县| 梓潼县| 南宁市| 静乐县| 长阳| 兴安县| 哈尔滨市| 内丘县| 新乡市| 方山县| 平顶山市| 阿拉善右旗| 宜阳县| 贞丰县| 武川县| 临湘市| 普兰县|