Asp.Net 請求處理機制
前言
咱們都知道Web請求響應是基於Http協議,那麼咱們能夠這樣來理解,一次Web請求和響應的過程,實際上就是一次發送Http請求和接收Http響應的過程。
客戶端向服務器發送一次Http請求,服務器端接收到此次請求,並生成響應報文
,將響應報文發送回客戶端。這樣客戶端和服務器端就完成了一次Web交互。
什麼是Asp.Net呢?
我喜歡把Asp.Net定義如:
Asp.Net 是一個運行在CLR的託管代碼上,從前到後處理Web請求,並響應Web請求的一個AOP框架,它是處理Web請求的一種引擎。它不是僅僅是咱們經常使用的WebForm,WebService,IHttpHandler這些,它還有不少.....
從瀏覽器到服務器的過程
,當請求到達web服務器的那一刻,web服務器Windows內核中的HTTP.SYS組件就會捕獲到請求。當HTTP.SYS組件分析到這是一個須要交給IIS服務器處理的Http請求時,HTTP.SYS組件就會將Request請求,交給IIS服務器來處理。IIS服務器分析Request請求的context-type類型,而後從處理程序映射表中去匹配,當在處理程序映射表中可以匹配到Request請求的context-type類型時,那麼IIS服務器就將請求交給映射表中所對應的程序處理。
當IIS發現,在處理程序映射表中沒有能匹配的項的時候(當沒有匹配項的時候,通常狀況下是請求"靜態文件"),就直接去下載Request請求所對應路徑的文件。如.jpg,html,xml.css文件等等。
圖二 : 從瀏覽器到達服務器的過程
回到以前,當服務器在處理如aspx.ashx,等等動態文件的時候,IIS服務器將Request請求,交
給aspnet_isapi.dll文件來處理。
ISAPI是第一個也是性能最高Request請求報文最原始的Web請求切入點
aspnet_isapi.dll是一個很是底層,而且是非託管的win32API,這個dll很是簡單,很是高效,而且還被微軟優化過性能。它用來處理最底層的 指令以及函數回調,併爲高層程序提供了應用程序級別服務的功能和接口。
當aspnet_isapi.dll接收到Request請求的時候,aspnet_isapi.dll就會去調動Web服務器中的.Net Framework,最終加載CLR運行環境,並建立一個ISAPIRuntime對象,而後調用ISAPIRuntime對象的ProcessRequest()方法。
ISAPIRuntme.ProcessRequest()方法是進入ASP.Net的第一個入口
ISAPIRuntime.ProcessRequest()方法調用以後主要作了一件事情,就是將Request的原始請求信息封裝成HttpWorkRequest類,因爲HttpWorkRequest類封裝的請求報文很原始,很複雜,因此微軟沒有將其公開出來。接着執行StartProcessing()方法,來建立HttpRuntime對象並調用其靜態方法ProcessRequest()。
圖三 : 如何開始ASP.Net
HttRuntime,HttpContext,HttpApplication ?
在HttpRuntime對象調用其靜態方法ProcessRequest()以後,咱們的Web請求開始慢慢進入應用層級別,why?
ProcessRequest()這個方法作了不少事情,具體能夠經過Reflector工具查看,可是大體分爲四個部分:
1.爲請求建立了一個新的HttpContext實例(這個對象就是咱們經常使用的HttpContext上下文對象),並將HttpWorkRequest中最原始的請求
報文封裝到HttpContext對象的HttpRequest對象中。
2.經過HttpApplicationFactory(應用程序工廠)獲得一個具體的HttpApplication 實例。
3.調用HttpApplication.Init()方法來創建事件請求管道。
4.Init()方法觸發了HttpApplication.ResumeProcessing()方法來開始執行Asp.Net事件請求管道。
圖四 : HttpRuntime,HttpApplication和HttpContext的關係
Asp.Net事件請求管道詳解
前面說Asp.Net是一個Aop框架,而Asp.Net事件請求管道就是一點。
Asp.Net事件請求管道,是微軟幫程序員提供來處理Web請求的一些列事件,這些事件是依次執行,咱們能夠經過在這些事件上註冊或移除咱們本身寫的方法,來修改Web請求執行的邏輯。
圖五 : ASP.Net事件請求管道
在第八個事件的時候,會建立請求的頁面對象,並轉換爲IHttpHandler接口。
在第九個事件到第十一個事件之間,會接收到瀏覽器發過來的SessionId。並先會將IHttpHandler接口嘗試轉換爲IRequiresSessionState接口,若是轉換成功,Asp.Net會根據這個SessionId到服務器的Session池中去查找所對應的Session對象,並將這個Session對象賦值到HttpContext對象的Session屬性。若是嘗試轉換爲IRequiresSessionState接口不成功,則不加載Session。
在第十一個事件到第十二個事件之間,會調用在第八個事件建立的頁面對象的ProcessRequest方法。
當咱們直接使用*.ashx頁面的時候,就直接調用了一個FrameworkInitialize(),並最終生成響應報文,發送回客戶端。
當咱們在使用*.aspx頁面的時候,它繼承自Page類,而Page類實現了IHttpHandler接口。
因爲Page類實現了IHttpHandler接口,在ProcessRequest方法中,調用了FrameworkInitialize()方法。
在FrameworkInitialize()這個方法內部就開始打造Asp.Net的頁面控件樹(打造html樹),在其中就調用了ProcessRequestMain方法,在這個方法裏面就執行了整個Asp.Net頁面生命週期。
IHttpModules
請求經過事件管道,一些列的事件被觸發了,咱們能夠經過在Global.asax全局配置文件中看到這些事件。
可是因爲這是由程序分配的事件,可能就不是咱們想要的。若是咱們想要建立一個可以複用的HttpApplication事件管道來處理Web請求,
咱們又想將這些代碼複用,或者開發成插件的形式。那麼咱們就能夠使用IHttpModules。
IHttpModules配置很簡單,咱們只須要在Web.config裏面配置一下就能夠了。而具體的HttpModules只須要實現IHttpModules接口,並註冊本身的方法就好了。
<?xml version="1.0"?>
<system.web>
<httpModules>
<add name="cnblogsHttpModules" type="cnblogs.cnblogsHttpModules"/>
</httpModules>
</system.web>
</configuration>
Web.config文件的配置
publicclass cnblogsHttpModules : IHttpModule
{
public void MyBeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
application.Context.Response.Write("這個IHttpModule具體類的寫法喲!");
}
}
具體的HttpModules類寫法
Asp.Net頁面生命週期詳解
Asp.Net是一個Aop框架,而Asp.Net事件請求管道體現了Aop思想,而如今咱們要說的Asp.Net頁面生命週期也體現Aop思想。
Asp.Net頁面生命週期的本質就是微軟提供給咱們程序員修改頁面控件樹代碼的一些列事件,咱們能夠經過實現頁面生命週期的事件方法來修改控件樹代碼。
圖六 : ASP.Net頁面生命週期
當ASP.Net執行完咱們註冊的生命週期事件方法的時候,最後會調用Render方法,Render方法要求傳入一個TextWriter文本寫出器對象,並遍歷全部控件樹,調用每一個控件的Render方法。
因此每個控件調用Render方法以後產生的Html字符串都依次寫入到TextWriter對象。最後ASP.Net將TextWriter中的Html字符串封裝成響應報文,而後發送回客戶端。
結束語
在這裏,我介紹了一下ASP.Net的整個處理請求的過程。但有不少底層的信息,我尚未仔細去觀察過,所以不少細節可能仍是沒有注意到。這篇文章可能仍是有不少錯誤的地方,但願博客園的兄弟姐妹們糾錯,謝謝。