上文說HttpProcessor在啟動(dòng)之后監(jiān)聽socket端口,如果socket端口有請(qǐng)求,該方法就調(diào)用方法connector.getContainer().invoke(request,response);去處理請(qǐng)求。接下來,我們來看看容器在整個(gè)請(qǐng)求處理過程中的作用。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名申請(qǐng)、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、睢陽網(wǎng)站維護(hù)、網(wǎng)站推廣。本文介紹最重要的四個(gè)容器:
1、Engine:表示整個(gè)Catalina的servlet引擎
2、Host:表示一個(gè)擁有數(shù)個(gè)上下文的虛擬主機(jī)
3、Context:表示一個(gè)Web應(yīng)用,一個(gè)context包含一個(gè)或多個(gè)wrapper
4、warpper:表示一個(gè)獨(dú)立的servlet
這四個(gè)容器都實(shí)現(xiàn)了接口Container,所以他們都叫容器,他們之間有上下級(jí)別的關(guān)系,如圖所示
1、簡單容器
連接器管理socket監(jiān)聽,一旦頁面有對(duì)應(yīng)端口請(qǐng)求,那么容器就來處理。也就是上文中說的這個(gè)方法。
connector.getContainer().invoke(request,response);
我們?cè)陧撁嬲?qǐng)求servlet是這個(gè)樣子的:http://localhost:8080/Primitive。那么這個(gè)URI是如何解析的呢?
首先引入Maper接口,mapper接口和容器關(guān)聯(lián),負(fù)責(zé)具體處理我們的URI對(duì)應(yīng)的servlet類。
publicinterfaceMapper{ /** *mapper關(guān)聯(lián)的容器 */ publicContainergetContainer(); /** 設(shè)置關(guān)聯(lián)容器 */ publicvoidsetContainer(Containercontainer); /**返回mapper對(duì)應(yīng)的協(xié)議 *ReturntheprotocolforwhichthisMapperisresponsible. */ publicStringgetProtocol(); /** *設(shè)置mapper對(duì)應(yīng)的協(xié)議 */ publicvoidsetProtocol(Stringprotocol); /**返回該請(qǐng)求的負(fù)責(zé)容器。*/ publicContainermap(Requestrequest,booleanupdate); } 簡單的Mapper接口實(shí)現(xiàn)如下: publicclassSimpleContextMapperimplementsMapper{ /**mapper關(guān)聯(lián)容器 */ privateSimpleContextcontext=null; publicContainergetContainer(){ return(context); } publicvoidsetContainer(Containercontainer){ if(!(containerinstanceofSimpleContext)) thrownewIllegalArgumentException ("Illegaltypeofcontainer"); context=(SimpleContext)container; } publicStringgetProtocol(){ returnnull; } publicvoidsetProtocol(Stringprotocol){ } /**返回處理這個(gè)請(qǐng)求的子容器 */ publicContainermap(Requestrequest,booleanupdate){ //獲取URI StringcontextPath= ((HttpServletRequest)request.getRequest()).getContextPath(); StringrequestURI=((HttpRequest)request).getDecodedRequestURI(); StringrelativeURI=requestURI.substring(contextPath.length()); // Wrapperwrapper=null; StringservletPath=relativeURI; StringpathInfo=null; //從容器的servletMappings字段獲得servlet名稱。 Stringname=context.findServletMapping(relativeURI); if(name!=null) //從容器的children字段中獲得該servlet名稱對(duì)應(yīng)的Wrapper類實(shí)例 wrapper=(Wrapper)context.findChild(name); return(wrapper); } }
代碼中map方法返回了我們請(qǐng)求URI對(duì)應(yīng)的處理容器。簡單的處理容器主要就是處理我們請(qǐng)求的servlet。具體的他包含兩個(gè)方面的內(nèi)容:
1、生成servlet實(shí)例。
2、為管道添加處理邏輯。
生成servlet實(shí)例主要就是通過類加載器加載servlet類。然后實(shí)例化該servlet類并且調(diào)用init()方法執(zhí)行實(shí)例初始化過程。為管道添加邏輯就涉及到了管道和Vavle的概念。
管道其實(shí)就是一個(gè)責(zé)任鏈,為servlet初始化后添加一些處理邏輯Vavle??创a:
publicclassSimplePipelineimplementsPipeline{ publicSimplePipeline(Containercontainer){ setContainer(container); } //基礎(chǔ)的Valve可有可無 protectedValvebasic=null; //該P(yáng)ipleline關(guān)聯(lián)的容器 protectedContainercontainer=null; //該pipeline包含的valves數(shù)組 protectedValvevalves[]=newValve[0]; //添加valve publicvoidaddValve(Valvevalve){ if(valveinstanceofContained) //為valve設(shè)置容器為當(dāng)前類的容器。 ((Contained)valve).setContainer(this.container); //線程安全擴(kuò)容放置新增vavles synchronized(valves){ Valveresults[]=newValve[valves.length+1]; System.arraycopy(valves,0,results,0,valves.length); results[valves.length]=valve; valves=results; } } publicvoidinvoke(Requestrequest,Responseresponse) throwsIOException,ServletException{ //生成內(nèi)部類SimplePipelineValveContext調(diào)用責(zé)任鏈 (newSimplePipelineValveContext()).invokeNext(request,response); } publicvoidremoveValve(Valvevalve){ } //內(nèi)部類 protectedclassSimplePipelineValveContextimplementsValveContext{ protectedintstage=0; publicStringgetInfo(){ returnnull; } //責(zé)任鏈調(diào)用 publicvoidinvokeNext(Requestrequest,Responseresponse) throwsIOException,ServletException{ intsubscript=stage; stage=stage+1; //InvoketherequestedValveforthecurrentrequestthread if(subscript<valves.length){ valves[subscript].invoke(request,response,this); } elseif((subscript==valves.length)&&(basic!=null)){ basic.invoke(request,response,this); } else{ thrownewServletException("Novalve"); } } }//endofinnerclass }
2、管道的原理。
管道其實(shí)就是一個(gè)責(zé)任鏈,他把需要處理的邏輯全部都組裝成為Vavle然后一個(gè)一個(gè)的去執(zhí)行,沒執(zhí)行一個(gè)首先是要去調(diào)下一個(gè)Vavle,如果調(diào)用到底部沒有其他了那就執(zhí)行邏輯,返回之后就繼續(xù)執(zhí)行它上面的Vavle。
代碼實(shí)現(xiàn):
從連接器過來的請(qǐng)求首先調(diào)用了容器的invoker()。invoker里面就是去執(zhí)行管道里面的邏輯處理。
publicvoidinvoke(Requestrequest,Responseresponse) throwsIOException,ServletException{ pipeline.invoke(request,response); } 管道的invoker需要調(diào)用責(zé)任鏈,那么他首先生成了內(nèi)部類,然后調(diào)用invokeNext()方法去執(zhí)行業(yè)務(wù)邏輯。 publicvoidinvoke(Requestrequest,Responseresponse) throwsIOException,ServletException{ //InvokethefirstValveinthispipelineforthisrequest (newSimplePipelineValveContext()).invokeNext(request,response); } protectedclassSimplePipelineValveContextimplementsValveContext{ protectedintstage=0; publicStringgetInfo(){ returnnull; } publicvoidinvokeNext(Requestrequest,Responseresponse) throwsIOException,ServletException{ intsubscript=stage; stage=stage+1; //InvoketherequestedValveforthecurrentrequestthread if(subscript<valves.length){ valves[subscript].invoke(request,response,this); } elseif((subscript==valves.length)&&(basic!=null)){ basic.invoke(request,response,this); } else{ thrownewServletException("Novalve"); } } }//endofinnerclass
本文標(biāo)題:servlet解析演進(jìn)(3)-容器
網(wǎng)站地址:http://www.rwnh.cn/article34/cgsese.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、網(wǎng)站制作、響應(yīng)式網(wǎng)站、品牌網(wǎng)站制作、全網(wǎng)營銷推廣、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)