您好,登錄后才能下訂單哦!
WEB應(yīng)用是怎么被部署的,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
一個(gè)WEB應(yīng)用,無論是解壓后的目錄,還是一個(gè)壓縮的WAR文件,都支持部署到應(yīng)用服務(wù)器中。
一個(gè)WEB應(yīng)用安裝到應(yīng)用服務(wù)器的過程,我們稱為部署。
部署應(yīng)用的形式又分多種:
靜態(tài)的:即應(yīng)用服務(wù)器啟動(dòng)時(shí)就存在在Server中的應(yīng)用。
動(dòng)態(tài)的:即應(yīng)用服務(wù)器運(yùn)行時(shí)動(dòng)態(tài)的把應(yīng)用添加應(yīng)用服務(wù)器中,支持應(yīng)用的請(qǐng)求。
動(dòng)態(tài)部署的實(shí)現(xiàn)在Tomcat中可以通過其自動(dòng)部署特性來完成。
也可以通過Tomcat的Manager應(yīng)用來實(shí)現(xiàn)遠(yuǎn)程部署。
我們今天先來看一下Tomcat的自動(dòng)部署實(shí)現(xiàn)原理。
整個(gè)HostConfig中涉及到多種類型的部署
自動(dòng)部署的時(shí)候,我們常規(guī)操作是直接把一個(gè)標(biāo)準(zhǔn)WAR應(yīng)用放到
%Tomcat_HOME%/webapps
目錄下,而后臺(tái)線程會(huì)定時(shí)掃描,發(fā)現(xiàn)有需要部署的應(yīng)用,就會(huì)啟動(dòng)部署流程進(jìn)行應(yīng)用部署。對(duì)于后臺(tái)線程,感興趣的朋友可以看前面的文章:
對(duì)于過期的session,Tomcat做了什么?
后臺(tái)線程發(fā)現(xiàn)了我們的應(yīng)用后,會(huì)調(diào)用到
HostConfig
類中的
deployWar
方法。
由于Tomcat支持以context.xml這種提供xml配置格式的應(yīng)用部署等,所以方法內(nèi)有大量判斷各類部署情況的邏輯。
最終,一個(gè)Web應(yīng)用會(huì)對(duì)應(yīng)到一個(gè)StandardContext
對(duì)象上,一個(gè)Web應(yīng)用又會(huì)被部署到一個(gè)虛擬主機(jī)上。
最核心的邏輯是下面這幾行:
Class<?> clazz = Class.forName(host.getConfigClass()); LifecycleListener listener = (LifecycleListener) clazz.newInstance(); context.addLifecycleListener(listener); context.setName(cn.getName()); context.setPath(cn.getPath()); context.setWebappVersion(cn.getVersion()); context.setDocBase(cn.getBaseName() + ".war"); host.addChild(context);
在設(shè)置完Context的屬性后,將其添加到虛擬主機(jī)上? host.addChild(context)
在·addChild·的邏輯中,主要是把這個(gè)應(yīng)用啟動(dòng)起來
// Start child if ((getState().isAvailable() || LifecycleState.STARTING_PREP.equals(getState())) && startChildren) { try { child.start(); } catch (LifecycleException e) { log.error("ContainerBase.addChild: start: ", e); throw new IllegalStateException ("ContainerBase.addChild: start: " + e); } }
此處,啟動(dòng)內(nèi)會(huì)處理許多事情,像Webapp的ClassLoader設(shè)置是否使用雙親委托,web.xml
和default web.xml
的merge,以及解析應(yīng)用中是否包含web-fragement.xml
,將多項(xiàng)配置合并后,這項(xiàng)工作是在ContextConfig
類內(nèi)完成的。
解析完web.xml后,會(huì)生成一個(gè)Webxml對(duì)象,需要根據(jù)具體的應(yīng)用配置信息,初始化我們的組件了,例如Filter,Listener等,
例如下面的邏輯
private void configureContext(WebXml webxml) { for (FilterDef filter : webxml.getFilters().values()) { if (filter.getAsyncSupported() == null) { filter.setAsyncSupported("false"); } context.addFilterDef(filter); } for (FilterMap filterMap : webxml.getFilterMappings()) { context.addFilterMap(filterMap); } context.setJspConfigDescriptor(webxml.getJspConfigDescriptor()); for (String listener : webxml.getListeners()) { context.addApplicationListener(listener); } for (ServletDef servlet : webxml.getServlets().values()) { Wrapper wrapper = context.createWrapper(); wrapper.setOverridable(servlet.isOverridable()); context.addChild(wrapper); } }
整個(gè)解析出的Servlet組件,又會(huì)被做為Context的子組件添加到應(yīng)用中。
在解析完Servlet等組件后,會(huì)再根據(jù)配置設(shè)置Session的超時(shí)時(shí)間,SessionCookie的名稱等。對(duì)這一部分,可以看前面的文章:深入Tomcat源碼分析Session到底是個(gè)啥!
一切都OK后,設(shè)置應(yīng)用的配置狀態(tài)
// Make our application available if no problems were encountered if (ok) { context.setConfigured(true); } else { log.error(sm.getString("contextConfig.unavailable")); context.setConfigured(false); }
再然后,就是對(duì)于filter
和listener
等組件的啟動(dòng)了。這些組件的啟動(dòng)是根據(jù)前一個(gè)組件是否啟動(dòng)成功,再?zèng)Q定是否繼續(xù)
if (!getConfigured()) { log.error( "Error getConfigured"); ok = false; } // Configure and call application event listeners if (ok) { if (!listenerStart()) { log.error( "Error listenerStart"); ok = false; }
根據(jù)Servlet規(guī)范進(jìn)行的容器實(shí)現(xiàn),都是先進(jìn)行l(wèi)istener的啟動(dòng),再進(jìn)行filter啟動(dòng)??赡苣程烀嬖嚂r(shí)會(huì)有人問到,或者涉及到應(yīng)用組件加載問題時(shí),記的在這里看到過。
在組件等全部啟動(dòng)完畢后,整個(gè)應(yīng)用部署就完成了。
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。