最近在國外的網(wǎng)站亂走一通,發(fā)現(xiàn)一些比較好的文章,收集整理加于自己的理解,作為筆記形式記錄下來,讓以后自己有個(gè)回憶。
ASP.NET是一個(gè)非常強(qiáng)大的構(gòu)建Web應(yīng)用的平臺(tái),它提供了極大的靈活性和能力以致于可以用它來構(gòu)建所有類型的Web應(yīng)用.絕大多數(shù)的人只熟悉高層的框架如WebForms和WebServices-這些都在ASP.NET層次結(jié)構(gòu)在最高層.在這篇文章中我將會(huì)討論ASP.NET的底層機(jī)制并解釋請求(request)是怎么從Web服務(wù)器傳送到ASP.NET運(yùn)行時(shí)然后如何通過ASP.NET管道來處理請求.
ASP.NET是一個(gè)請求處理引擎.它接收一個(gè)發(fā)送過來的請求,把它傳給內(nèi)部的管道直到終點(diǎn),作為一個(gè)開發(fā)人員的你可以在這里附加一些代碼來處理請求.這個(gè)引擎是和HTTP/Web服務(wù)器完全分隔的.事實(shí)上,HTTP運(yùn)行時(shí)是一個(gè)組件,使你可以擺脫IIS或者任何其他的服務(wù)器程序,將你自己的程序寄宿在內(nèi).
運(yùn)行時(shí)提供了一個(gè)復(fù)雜但同時(shí)非常優(yōu)雅的在管道中路由請求的機(jī)制.其中有很多相關(guān)的對(duì)象,大多數(shù)都是可擴(kuò)展的(通過繼承或者事件接口),在幾乎所有的處理流程上都是如此.所以這個(gè)框架具有高度可擴(kuò)展性.通過這個(gè)機(jī)制,掛接到非常底層的接口(比如緩存,認(rèn)證和授權(quán))都變得可能了.你甚至可以在預(yù)處理或者處理后過濾內(nèi)容,也可以簡單的將符合特殊標(biāo)記的請求直接路由你的代碼或者另一個(gè)URL上.存在著許多不同的方法來完成同一件事,但是所有這些方法都是可以簡單直接地實(shí)現(xiàn)的,同時(shí)還提供了靈活性,可以得到最好的性能和開發(fā)的簡單性.
整個(gè)ASP.NET引擎是完全建立在托管代碼上的,所有的擴(kuò)展功能也是通過托管代碼擴(kuò)展來提供的.這是對(duì).NET框架具有構(gòu)建復(fù)雜而且高效的框架的能力的最好的證明.ASP.NET最令人印象深刻的地方是深思熟慮的設(shè)計(jì),使得框架非常的容易使用,又能提供掛接到請求處理的幾乎所有部分的能力.
互的ASP.NET在微軟的平臺(tái)上就是通過ISAPI擴(kuò)展來和IIS進(jìn)行交,這個(gè)擴(kuò)展寄宿著.NET運(yùn)行時(shí)和ASP.NET運(yùn)行時(shí).ISAPI提供了核心的接口,ASP.NET使用非托管的ISAPI代碼通過這個(gè)接口來從Web服務(wù)器獲取請求,并發(fā)送響應(yīng)回客戶端.ISAPI提供的內(nèi)容可以通過通用對(duì)象(例如HttpRequest和HttpResponse)來獲取,這些對(duì)象通過一個(gè)定義良好并有很好訪問性的接口來暴露非托管數(shù)據(jù).
當(dāng)用戶發(fā)送一個(gè)URL請求時(shí),在Web服務(wù)器端,IIS5或6,獲得這個(gè)請求.在最底層,ASP.NET和IIS通過ISAPI擴(kuò)展進(jìn)行交互.在ASP.NET環(huán)境中這個(gè)請求通常被路由到一個(gè)擴(kuò)展名為.aspx的頁面上,但是這個(gè)流程是怎么工作的完全依賴于處理特定擴(kuò)展名的HTTP Handler是怎么實(shí)現(xiàn)的.在IIS中.aspx通過’應(yīng)用程序擴(kuò)展’(又稱為腳本映射)被映射到ASP.NET的ISAPI擴(kuò)展DLL-aspnet_isapi.dll.每一個(gè)請求都需要通過一個(gè)被注冊到aspnet_isapi.dll的擴(kuò)展名來觸發(fā)ASP.NET(來處理這個(gè)請求).
ISAPI是底層的非托管Win32 API.ISAPI定義的接口非常簡單并且是為性能做了優(yōu)化的.它們是非常底層的-處理指針和函數(shù)指針表來進(jìn)行回調(diào)-但是它們提供了最底層和面向效率的接口,使開發(fā)者和工具提供商可以用它來掛接到IIS上.因?yàn)镮SAPI非常底層所以它并不適合來開發(fā)應(yīng)用級(jí)的代碼,而且ISAPI傾向于主要被用于橋接接口,向上層工具提供應(yīng)用服務(wù)器類型的功能.
下面來介紹HttpRuntime,HttpContext,HttpApplication
當(dāng)一個(gè)請求到來時(shí),它被路由到ISAPIRuntime.ProcessRequest()方法.這個(gè)方法調(diào)用HttpRuntime.ProcessRequest方法,它作一些重要的事情
為請求創(chuàng)建一個(gè)新的HttpContext實(shí)例
獲取一個(gè)HttpApplication實(shí)例
調(diào)用HttpApplication.Init()方法來設(shè)置管道的事件
Init()方法觸發(fā)開始ASP.NET管道處理的HttpApplication.ResumeProcessing()方法
首先一個(gè)新的HttpContext對(duì)象被創(chuàng)建并用來傳遞ISAPIWorkerRequest,這個(gè)上下文在整個(gè)請求的生命周期總都是可用的并總可以通過靜態(tài)屬性.
HttpContext.Currect來訪問.正像名字所暗示的那樣,HttpContext對(duì)象代表了當(dāng)前活動(dòng)請求的上下文因?yàn)樗嗽谡埱笊芷谥兴械湫偷哪阈枰L問的重要對(duì)象:Request,Response,Application,Server,Cache.在請求處理的任何時(shí)候HttpContext.Current給你訪問所有這些的能力.
HttpContext對(duì)象也包含一個(gè)非常有用的Items集合,你可以用它來保存針對(duì)特定請求的數(shù)據(jù).上下文對(duì)象在請求周期的開始時(shí)被創(chuàng)建,在請求結(jié)束時(shí)被釋放,所有在Items集合中保存的數(shù)據(jù)只在這個(gè)特定的請求中可用.一個(gè)很好的使用的例子是請求日志機(jī)制,當(dāng)你通過想通過在Global.asax中掛接Application_BeginRequest和Application_EndRequest方法記錄請求的開始和結(jié)束時(shí)間(象在列表3中顯示的那樣).HttpContext對(duì)你就非常有用了-如果你在請求或頁面處理的不同部分需要數(shù)據(jù),你自由的使用它.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (App.Configuration.LogWebRequests)
{
Context.Items.Add("WebLog_StartTime",DateTime.Now);
}
}
protected void Application_EndRequest(Object sender, EventArgs e)
{
if (App.Configuration.LogWebRequests)
{
try
{
TimeSpan Span = DateTime.Now.Subtract((DateTime) Context.Items["WebLog_StartTime"] );
int MiliSecs = Span.TotalMilliseconds;
WebRequestLog.Log(App.Configuration.ConnectionString, true, MilliSecs);
}
}
}
HttpApplication
每個(gè)請求都被路由到一個(gè)HttpApplication對(duì)象上.HttpApplicationFactory類根據(jù)應(yīng)用程序的負(fù)載為你的ASP.NET應(yīng)用創(chuàng)建一個(gè)HttpApplication對(duì)象池并為每個(gè)請求分發(fā)HttpApplication對(duì)象的引用.對(duì)象池的大小受machine.config文件中ProcessModel鍵中的MaxWorkerThreads設(shè)置限制.
HttpApplication是你的Web程序的外部包裝器,而且它被映射到在Global.asax里面定義的類上.它是進(jìn)入HttpRuntime的第一個(gè)入口點(diǎn).如果你查看Global.asax(或者對(duì)應(yīng)的代碼類)你會(huì)發(fā)現(xiàn)這個(gè)類直接繼承自HttpApplication:
HttpApplication的主要職責(zé)是作為Http管道的事件控制器,所以它的接口主要包含的是事件.事件掛接是非常廣泛的,大概包括以下這些:
BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest
HttpModule和HttpHandler兩者都是在HttpApplication.Init()函數(shù)調(diào)用的一部分中被載入并附加到調(diào)用鏈上
httpApplication它本身對(duì)發(fā)送給應(yīng)用程序的數(shù)據(jù)一無所知-它只是一個(gè)通過事件來通訊的消息對(duì)象.它觸發(fā)事件并通過HttpContext對(duì)象來向被調(diào)用函數(shù)傳遞消息.實(shí)際的當(dāng)前請求的狀態(tài)數(shù)據(jù)由前面提到的HttpContext對(duì)象維護(hù).它提供了所有請求專有的數(shù)據(jù)并從進(jìn)入管道開始到結(jié)束一直跟隨請求
一旦管道被啟動(dòng),HttpApplication開始象圖六那樣一個(gè)個(gè)的觸發(fā)事件.每個(gè)事件處理器被觸發(fā),如果事件被掛接,這些處理器將執(zhí)行它們自己的任務(wù).這個(gè)處理的主要任務(wù)是最終調(diào)用掛接到此特定請求的HttpHandler.處理器(handler)是ASP.NET請求的核心處理機(jī)制,通常也是所有應(yīng)用程序級(jí)別的代碼被執(zhí)行的地方.記住ASP.NET頁面和Web服務(wù)框架都是作為HttpHandler實(shí)現(xiàn),這里也是處理請求的的核心之處.模塊(module)趨向于成為一個(gè)傳遞給處理器(handler)的上下文的預(yù)處理或后處理器.ASP.NET中典型的默認(rèn)處理器包括預(yù)處理的認(rèn)證,緩存以及后處理中各種不同的編碼機(jī)制.
雖然HttpModule看上去很像ISAPI過濾器,它們都檢查每個(gè)通過ASP.NET應(yīng)用的請求,但是它們只檢查映射到單個(gè)特定的ASP.NET應(yīng)用或虛擬目錄的請求,也就是只能檢查映射到ASP.NET的請求.這樣你可以檢查所有ASPX頁面或者其他任何映射到ASP.NET的擴(kuò)展名.
實(shí)現(xiàn)一個(gè)HTTP模塊是非常簡單的:你必須實(shí)現(xiàn)之包含兩個(gè)函數(shù)(Init()和Dispose())的IHttpModule接口.傳進(jìn)來的事件參數(shù)中包含指向HTTPApplication對(duì)象的引用,這給了你訪問HttpContext對(duì)象的能力.在這些方法上你可以掛接到HttpApplication事件上.例如,如果你想掛接AuthenticateRequest事件到一個(gè)模塊上
總的來說w3wp.exe調(diào)用.NET類庫進(jìn)行具體處理,順序如下:ISAPIRuntim, HttpRuntime, HttpApplicationFactory, HttpApplication, HttpModule, HttpHandlerFactory, HttpHandler
有時(shí)間再對(duì)每個(gè)對(duì)象正進(jìn)深入理解.
聯(lián)系客服