日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat源码分析(十)--部署器 转载

發(fā)布時(shí)間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat源码分析(十)--部署器 转载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本系列轉(zhuǎn)載自?http://blog.csdn.net/haitao111313/article/category/1179996?

? 我們知道,在Tomcat的世界里,一個(gè)Host容器代表一個(gè)虛機(jī)器資源,Context容器代表一個(gè)應(yīng)用,所謂的部署器就是能夠把Context容器添加進(jìn)Host容器中去的一個(gè)組件。顯然,一個(gè)Host容器應(yīng)該擁有一個(gè)部署器組件。簡(jiǎn)單的部署代碼應(yīng)該是下面這樣的:

[java]?view plaincopyprint?
  • Context?context?=?new?StandardContext();??
  • Host?host?=?new?StandardHost();??
  • host.addChild(context);??
  • 別看這簡(jiǎn)單,其實(shí)這就是核心的部署代碼。當(dāng)然,Tomcat的部署器絕不是這么點(diǎn)東西,但其實(shí)也是比較簡(jiǎn)單的東西。在Catalina的createStartDigester()方法中(具體怎么調(diào)用到這個(gè)方法,詳細(xì)參考Tomcat源碼分析(一)--服務(wù)啟動(dòng)),向StandardHost容器中添加了一個(gè)HostConfig的實(shí)例。HostConfig類實(shí)現(xiàn)了LifecycleListener接口,也就是說(shuō)它是個(gè)監(jiān)聽器類,能監(jiān)聽到組件的生命周期事件(有關(guān)生命周期的東西請(qǐng)參看Tomcat源碼分析(七)--單一啟動(dòng)/關(guān)閉機(jī)制(生命周期))。? 下面看接受事件的方法lifecycleEvent(LifecycleEvent)做了寫什么工作:

    [java]?view plaincopyprint?
  • public?void?lifecycleEvent(LifecycleEvent?event)?{??
  • ??
  • ????????//?Identify?the?host?we?are?associated?with??
  • ????????try?{??
  • ????????????host?=?(Host)?event.getLifecycle();??
  • ????????????if?(host?instanceof?StandardHost)?{?//如果監(jiān)聽到的事件對(duì)象類型是StandardHost就設(shè)置相關(guān)屬性。??
  • ????????????????int?hostDebug?=?((StandardHost)?host).getDebug();??
  • ????????????????if?(hostDebug?>?this.debug)?{??
  • ????????????????????this.debug?=?hostDebug;??
  • ????????????????}??
  • ????????????????setDeployXML(((StandardHost)?host).isDeployXML());//是否發(fā)布xml文件的標(biāo)識(shí),默認(rèn)為true??
  • ????????????????setLiveDeploy(((StandardHost)?host).getLiveDeploy());//是否動(dòng)態(tài)部署標(biāo)識(shí),默認(rèn)為true??
  • ????????????????setUnpackWARs(((StandardHost)?host).isUnpackWARs());//是否要將war文件解壓縮,默認(rèn)為true??
  • ????????????}??
  • ????????}?catch?(ClassCastException?e)?{??
  • ????????????log(sm.getString("hostConfig.cce",?event.getLifecycle()),?e);??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????//?Process?the?event?that?has?occurred??
  • ????????if?(event.getType().equals(Lifecycle.START_EVENT))?//監(jiān)聽到容器開始,則調(diào)用start方法,方法里面調(diào)用了部署應(yīng)用的代碼??
  • ????????????start();??
  • ????????else?if?(event.getType().equals(Lifecycle.STOP_EVENT))??
  • ????????????stop();??
  • ??
  • ????}??
  • 如果監(jiān)聽到StandardHost容器啟動(dòng)開始了,則調(diào)用start方法來(lái),下面看start方法:

    [java]?view plaincopyprint?
  • protected?void?start()?{??
  • ??
  • ???????if?(debug?>=?1)??
  • ???????????log(sm.getString("hostConfig.start"));??
  • ??
  • ???????if?(host.getAutoDeploy())?{??
  • ???????????deployApps();//發(fā)布應(yīng)用??
  • ???????}??
  • ??
  • ???????if?(isLiveDeploy())?{??
  • ???????????threadStart();//動(dòng)態(tài)發(fā)布應(yīng)用,因?yàn)镠ostConfig也實(shí)現(xiàn)了Runnable接口,threadStart啟動(dòng)該線程來(lái)實(shí)現(xiàn)動(dòng)態(tài)發(fā)布??
  • ???????}??
  • ??
  • ???}??
  • ??--------------------》deployApps方法,該方法會(huì)把webapps目錄下的所有目錄都看作成一個(gè)應(yīng)用程序??
  • ????protected?void?deployApps()?{??
  • ??
  • ???????if?(!(host?instanceof?Deployer))??
  • ???????????return;??
  • ???????if?(debug?>=?1)??
  • ???????????log(sm.getString("hostConfig.deploying"));??
  • ??
  • ???????File?appBase?=?appBase();//返回webapps目錄??
  • ???????if?(!appBase.exists()?||?!appBase.isDirectory())??
  • ???????????return;??
  • ???????String?files[]?=?appBase.list();//列出webapps目錄下的所有文件??
  • ??
  • ???????deployDescriptors(appBase,?files);//通過描述符發(fā)布應(yīng)用??
  • ???????deployWARs(appBase,?files);//發(fā)布war文件的應(yīng)用??
  • ???????deployDirectories(appBase,?files);//發(fā)布目錄型的應(yīng)用??
  • ??
  • ???}??
  • 以上三個(gè)發(fā)布應(yīng)用的方式大同小異,所以只說(shuō)說(shuō)常用的發(fā)布方式--目錄型的應(yīng)用,下面看看deployDirectories方法,只寫了關(guān)鍵的邏輯:

    [java]?view plaincopyprint?
  • protected?void?deployDirectories(File?appBase,?String[]?files)?{??
  • ??
  • ?????for?(int?i?=?0;?i?<?files.length;?i++)?{??
  • ??
  • ?????????if?(files[i].equalsIgnoreCase("META-INF"))??
  • ?????????????continue;??
  • ?????????if?(files[i].equalsIgnoreCase("WEB-INF"))??
  • ?????????????continue;??
  • ?????????if?(deployed.contains(files[i]))??
  • ?????????????continue;??
  • ?????????File?dir?=?new?File(appBase,?files[i]);??
  • ?????????if?(dir.isDirectory())?{??
  • ??
  • ?????????????deployed.add(files[i]);??
  • ??
  • ?????????????//?Make?sure?there?is?an?application?configuration?directory??
  • ?????????????//?This?is?needed?if?the?Context?appBase?is?the?same?as?the??
  • ?????????????//?web?server?document?root?to?make?sure?only?web?applications??
  • ?????????????//?are?deployed?and?not?directories?for?web?space.??
  • ?????????????File?webInf?=?new?File(dir,?"/WEB-INF");??
  • ?????????????if?(!webInf.exists()?||?!webInf.isDirectory()?||??
  • ?????????????????!webInf.canRead())??
  • ?????????????????continue;??
  • ??
  • ?????????????//?Calculate?the?context?path?and?make?sure?it?is?unique??
  • ?????????????String?contextPath?=?"/"?+?files[i];??
  • ?????????????if?(files[i].equals("ROOT"))??
  • ?????????????????contextPath?=?"";??
  • ?????????????if?(host.findChild(contextPath)?!=?null)??
  • ?????????????????continue;??
  • ??
  • ?????????????//?Deploy?the?application?in?this?directory??
  • ?????????????log(sm.getString("hostConfig.deployDir",?files[i]));??
  • ?????????????try?{??
  • ?????????????????URL?url?=?new?URL("file",?null,?dir.getCanonicalPath());//得到應(yīng)用的路徑,路徑的寫法是???file://應(yīng)用名稱??
  • ?????????????????((Deployer)?host).install(contextPath,?url);?//安裝應(yīng)用到目錄下??
  • ?????????????}?catch?(Throwable?t)?{??
  • ?????????????????log(sm.getString("hostConfig.deployDir.error",?files[i]),??
  • ?????????????????????t);??
  • ?????????????}??
  • ??
  • ?????????}??
  • ??
  • ?????}??
  • ??
  • ?}??

  • ((Deployer) host).install(contextPath, url);會(huì)調(diào)用到StandardHost的install方法,再由StandardHost轉(zhuǎn)交給StandardHostDeployer的install方法,StandardHostDeployer是一個(gè)輔助類,幫助StandardHost來(lái)實(shí)現(xiàn)發(fā)布應(yīng)用,它實(shí)現(xiàn)了Deployer接口,看它的install(URL config, URL war)方法(它有兩個(gè)install方法,分別用來(lái)發(fā)布上面不同方式的應(yīng)用):

    [java]?view plaincopyprint?
  • public?synchronized?void?install(String?contextPath,?URL?war)??
  • ???????throws?IOException?{??
  • ??
  • ?????..............................................??
  • ??
  • ???????//?Calculate?the?document?base?for?the?new?web?application??
  • ???????host.log(sm.getString("standardHost.installing",??
  • ?????????????????????????????contextPath,?war.toString()));??
  • ???????String?url?=?war.toString();??
  • ???????String?docBase?=?null;??
  • ???????if?(url.startsWith("jar:"))?{???//如果是war類型的應(yīng)用??
  • ???????????url?=?url.substring(4,?url.length()?-?2);??
  • ???????}??
  • ???????if?(url.startsWith("file://"))//如果是目錄類型的應(yīng)用??
  • ???????????docBase?=?url.substring(7);??
  • ???????else?if?(url.startsWith("file:"))??
  • ???????????docBase?=?url.substring(5);??
  • ???????else??
  • ???????????throw?new?IllegalArgumentException??
  • ???????????????(sm.getString("standardHost.warURL",?url));??
  • ??
  • ???????//?Install?the?new?web?application??
  • ???????try?{??
  • ???????????Class?clazz?=?Class.forName(host.getContextClass());//host.getContextClass得到的其實(shí)是StandardContext,??
  • ???????????Context?context?=?(Context)?clazz.newInstance();??
  • ???????????context.setPath(contextPath);//設(shè)置該context的訪問路徑為contextPath,即我們的應(yīng)用訪問路徑??
  • ?????????????
  • ???????????context.setDocBase(docBase);//設(shè)置該應(yīng)用在磁盤的路徑??
  • ???????????if?(context?instanceof?Lifecycle)?{??
  • ???????????????clazz?=?Class.forName(host.getConfigClass());//實(shí)例化host的監(jiān)聽器類,并關(guān)聯(lián)上context??
  • ???????????????LifecycleListener?listener?=??
  • ???????????????????(LifecycleListener)?clazz.newInstance();??
  • ???????????????((Lifecycle)?context).addLifecycleListener(listener);??
  • ???????????}??
  • ???????????host.fireContainerEvent(PRE_INSTALL_EVENT,?context);??
  • ???????????host.addChild(context);???????????//添加到host實(shí)例,即把context應(yīng)用發(fā)布到host。??
  • ???????????host.fireContainerEvent(INSTALL_EVENT,?context);??
  • ???????}?catch?(Exception?e)?{??
  • ???????????host.log(sm.getString("standardHost.installError",?contextPath),??
  • ????????????????????e);??
  • ???????????throw?new?IOException(e.toString());??
  • ???????}??
  • ??
  • ???}??

  • 經(jīng)過上面的代碼分析,已經(jīng)完全了解了怎么發(fā)布一個(gè)目錄型的應(yīng)用到StandardHost中,其他war包和文件描述符類型的應(yīng)用發(fā)布跟StandardHost大體類似,在這里就不說(shuō)了,有興趣的可以自己查看源代碼。

    轉(zhuǎn)載于:https://www.cnblogs.com/chenying99/archive/2012/12/02/2798452.html

    總結(jié)

    以上是生活随笔為你收集整理的Tomcat源码分析(十)--部署器 转载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。