生活随笔
收集整理的這篇文章主要介紹了
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ò),歡迎將生活随笔推薦給好友。