ASP.Net请求小周期
ASP.NET請求處理全過程
一個ASP.NET請求過程中,從瀏覽器中發出一個Web請求 到 這個請求被響應并顯示在瀏覽器中的過程中究竟會發生哪些不同的事件,當我們進入這個事件之旅時,我們也會試著明白在請求處理的每個事件當中我們可以做什么業務邏輯處理操作。
首先把整個過程大致分成兩步:
- ASP.NET會創建一個能夠處理請求的環境。換句話說,它會創建一個包含請求、響應以及上下文對象的應用程序對象來處理這個請求。
- 一旦ASP.NET環境被創建,用戶請求就會通過由modules(管道)、handlers(處理程序)和page objects(頁面對象)觸發的一系列事件進行處理。簡而言之,我們暫且將此步稱為MHPM(Module、Handler、Page和Module Event)。
ASP.NET環境的創建
- 第一步:用戶請求到達IIS后,發現處理不了這個后綴的文件,就去查找映射表。IIS首先會檢查哪一個ISAPI擴展能夠處理這個請求,這會取決于文件的后綴名。例如:如果請求的是一個'.aspx'的頁面,那么就會被傳遞到'aspnet_isapi.dll'來進行處理。
- 第二步:如果這是該網站的首次請求,那么一個稱為'ApplicationManager'的類會首先創建一個該網站可以運行的應用程序域(App Domain)。正如我們所知,應用程序域隔離部署在同一臺IIS服務器上的兩個不同的Web應用程序。因此,即使其中一個應用程序域出現了錯誤,也不會影響其他應用程序域的正常運作。
應用程序域
.NET平臺下,程序集并沒有直接加載進 進程 中(傳統的Win32程序是直接承載的)。.NET可執行程序承載在進程的一個邏輯分區中,術語稱應用程序域(簡稱AppDomain)。應用程序域是.NET引入的一個新概念,它比進程所占用的資源要少,可以被看作是一個 輕量級的進程。
- 第三步:在新創建的應用程序域中,會創建ASP.NET的宿主環境,也就是HttpRuntime對象。一旦宿主環境被創建完成,網站調用HttpRuntime類的靜態方法處理請求,ASP.NET最核心的對象如HttpContext、HttpRequest和HttpResponse對象都會被創建好。HttpApplication對象將會被分配給一系列的ASP.NET核心對象來處理請求的頁面。
這里面主要包括:
- 分析請求報文,并將報文數據封裝到一個叫HttpWorkRequest類對象應用的屬性中
- 通過調用HttpApplicationFactory類的一個靜態方法創建HttpApplication對象(這里每次HttpApplicationFactory都會到HttpApplication池中去查找,看看有沒用空閑的HttpApplication對象,如果有,就直接拿來使用,否則才創建新的使用,網站針對此次請求的所有運行過程都在這個對象中完成)
如果你的系統中存在一個global.asax文件,那么這個global.asax文件的對象也會被創建。但是,需要注意的是你的global.asax需要繼承自HttpApplication類。
global.asax
Global.asax 文件(也稱作 ASP.NET 應用程序文件)是可選文件,包含用于響應 ASP.NET 或 HttpModule 引發的應用程序級別事件的代碼。(換句話說,我們可以自定義后面我們所要介紹的一些事件,因為請求處理流程會經歷后面的10多個事件,我們可以寫代碼來自定義其中的一些事件,加一些我們想做的業務邏輯操作,比如:URL重寫、身份驗證、圖片水印等等。)
-
創建HttpContext對象,這個對象是當前請求的上下文環境,里面包含處理請求的所有參數數據,其中最重要的就是HttpRequest和HttpResponse對象。
HttpRequest
對象主要包含了所有的請求信息,這些信息來源于HttpWorkRequest對象中包含的屬性:Form(客戶端表單數據)、QueryString(客戶端url參數)
HttpResponse
主要包含了TestWriter對象,用來保存頁面類型執行過程中要輸入給瀏覽器的數據
- 因為HttpApplication里面運行IHttpHandler handler=(通過反射方式創建的被請求頁面類對象) 被請求頁面對象里的ProcessRequest方法,所以,需要將HttpContext對象傳入到HttpApplication中來,即HttpApplication對象將會被分配給一系列的ASP.NET核心對象來處理請求的頁面
- 第四步:這時,HttpApplication開始通過HTTP管道事件、處理程序(Handlers)和頁面事件來處理請求了。也就是說:它會觸發 MHPM 中的事件來處理請求。
下圖則形象地展示了在一個ASP.NET請求過程中的重要內部對象模型。最高層是ASP.NET運行時,它創建了一個應用程序域(AppDoamin),下層則創建了一個包含request、response以及context對象的HttpRuntime。
.NET平臺處理HTTP請求的過程大致如下:
- 1、IIS得到一個請求;
- 2、查詢腳本映射擴展,然后把請求映射到aspnet_isapi.dll文件
- 3、代碼進入工作者進程(IIS5里是aspnet_wp.exe;IIS6里是w3wp.exe),工作者進程也叫輔助進程;
- 4、.NET運行時被加載;
- 5、非托管代碼調用IsapiRuntime.ProcessRequest()方法;
- 6、每一個請求調用一個IsapiWorkerRequest;
- 7、使用WorkerRequest調用HttpRuntime.ProcessRequest()方法;
- 8、通過傳遞進來的WorkerRequest創建一個HttpContext對象
- 9、通過把上下文對象作為參數傳遞給HttpApplication.GetApplicationInstance(),然后調用該方法,從應用程序池中獲取一個HttpApplication實例;
- 10、調用HttpApplication.Init(),啟動管道事件序列,鉤住模塊和處理器;
- 11、調用HttpApplicaton.ProcessRequest,開始處理請求;
- 12、觸發管道事件;
- 13、調用HTTP處理器和ProcessRequest方法;
- 14、把返回的數據輸出到管道,觸發處理請求后的事件。
- 當客戶端向Web服務器請求一個頁面文件時,這個HTTP請求會被inetinfo.exe進程截獲(WWW服務),它判斷文件后綴,如果是*.aspx、*.asmx等,就把這個請求轉交給aspnet_isapi.dll,而aspnet_isapi.dll則會通過一個Http PipeLine的管道,將這個HTTP請求發送給w3wq.exe進程,當這個HTTP請求進入w3wq.exe進程之后,Asp.Net framework就會通過HttpRuntime來處理這個HTTP請求,處理完畢后將結果返回給客戶端。當一個HTTP請求被送入到HttpRuntime之后,這個HTTP請求通過HTTP管道(HttpRuntime是HTTP管道的入口)被送入到一個被稱之為HttpApplication Factory的一個容器當中,而這個容器會給出一個HttpApplication實例來處理傳遞進來的HTTP請求,同時HttpApplication實例會創建一個HttpContext對象來記錄HTTP請求的上下文,而后這個HTTP請求會依次進入到如下幾個容器中:HttpModule --> HttpHandler Factory --> HttpHandler.當系統內部的HttpHandler的ProcessRequest方法處理完畢之后,整個Http Request就被處理完成了.如果想在中途截獲一個HttpRequest并做些自己的處理,就應該在HttpRuntime運行時內部來做到這一點,確切的說時在HttpModule這個容器中做到這個的。
通過MHPM觸發的事件處理請求
一旦HttpApplication創建好,它就開始處理請求了。它經歷了三個不同的部分:HttpModule、Page和HttpHandler。當它經過這些部分時,它將調用不同的事件,而這些事件的邏輯處理還可以由開發者來進行擴展和增加自定義處理。
先來了解一下什么是HttpModule和HttpHandlers。他們幫助我們在ASP.NET頁面處理過程的前后注入自定義的邏輯處理
他們之間主要的差別
如果你想要注入的邏輯是基于像'.aspx','.html'這樣的擴展名,那么你可以使用HttpHandler。換句話說,HttpHandler是一個基于處理器的擴展。
如果你想要在ASP.NET管道事件中注入邏輯,那么你可以使用HttpModule。也可以說,HttpModule是一個基于處理器的事件。
下面是請求處理過程的邏輯流程,其中有4個重要的步驟
- 第一步(M:HttpModule):客戶端請求開始被處理。在ASP.NET引擎執行和創建HttpModule觸發事件(在此過程中,你也可以注入自定義邏輯)之前,有6個事件你可以在頁面對象創建之前來使用,它們分別是:BeginRequest、AuthenticateRequest、AuthorizeRequest、ResolveRequestCache、AcquireRequestState 以及 PreRequestHandlerExecute。
- 第二步(H:HttpHandler):一旦以上6個事件被觸發后,ASP.NET引擎就將會調用 ProcessRequest 事件,即使你已經在項目中實現了HttpHandler。
- 第三步(P:ASP.NET Page):一旦HttpHandler邏輯執行,ASP.NET頁面對象就被創建了。而ASP.NET頁面被創建,一系列的事件也會隨之被觸發,它們可以幫助我們自定義邏輯注入到這些事件里邊。在此過程中,有6個重要事件給我們提供了占位符,以便我們在ASP.NET頁面中寫入邏輯,它們分別是:Init、Load、Validate、Render 和 Unload。你可以通過記住單詞SILVER來記憶這幾個事件,S—Start(沒有任何意義,僅僅是為了形成一個單詞),I(Init)、L(Load)、V(Validate)、E(Event)、R(Render)。
- 第四步(M:HttpModule):一旦頁面對象執行結束并從內存中被卸載,HttpModule提供了提交返回頁面的執行事件,同樣,在這些事件中也可以被注入自定義的返回處理邏輯。這里有4個重要的提交處理事件:PostRequestHandlerExecute、ReleaserequestState、UpdateRequestCache以及EndRequest
下圖形象地展示了上面的四個步驟:
對于執行HttpApplication的ProcessRequest方法這個過程可以看成一個管道,要先后按照順序執行19個委托事件,其中第八個時,創建 被請求的頁面對象,第11到12事件之間,執行了被創建的頁面類對象的ProcessRequest方法
什么是請求管道?
請求管道就是把Application的一系列事件串聯成一條線,這些事件按照排列的先后順序依次執行,事件處理的對象包括HttpModule、HttpHandler、ASP.NET Page
熟悉請求管道實現程序運行的全過程:
- BeginRequest:開始處理請求
- AuthenticateRequest:授權驗證請求,獲取用戶授權信息
- PostAuthenticateRequest:獲取成功
- AunthorizeRequest:授權,一般來檢查用戶是否獲得權限
- PostAuthorizeRequest:獲得授權
- ResolveRequestCache:獲取頁面緩存結果
- PostResolveRequestCache:已獲取緩存
- PostMapRequestHandler:創建頁面對象
- AcquireRequestState:獲取Session-----先判斷當前頁面對象是否實現了IRequiresSessionState接口,如果實現了,則從瀏覽器發來的請求報文體中獲得SessionID,并到服務器的Session池中獲得對應的Session對象,最后賦值給HttpContext的Session屬性
- PostAcquireRequestState:獲得Session
- PreRequestHandlerExecute:準備執行頁面對象,執行頁面對象的ProcessRequest方法
- PostRequestHandlerExecute:執行完頁面對象了
- ReleaseRequestState:釋放請求狀態
- PostReleaseRequestState:已釋放請求狀態
- UpdateRequestCache:更新緩存
- PostUpdateRequestCache:已更新緩存
- LogRequest:日志記錄
- PostLogRequest:已完成日志
- EndRequest完成
詳解ASP.NET頁面事件
在上面的部分中,我們已經了解了一個ASP.NET頁面請求事件的整體流程。那么,在其中一個最重要的部分就是ASP.NET頁面,但是我們并沒有對其進行詳細討論
每一個ASP.NET頁都有2個部分:一個是在瀏覽器中進行顯示的部分,它包含了HTML標簽、viewstate形式的隱藏域 以及 在HTML input中的數據。當這個頁面被提交到服務器時,這些HTML標簽會被創建到ASP.NET控件,并且viewstate還會和表單數據綁定在一起。一旦你在后置代碼中得到所有的服務器控件,你可以執行和寫入你自己的邏輯并呈現給客戶瀏覽器。
當頁面進行回發時,如點擊按鈕,以上事件都會重新執行一次,這時的執行順序為:
- OnPreInit
- OnInit
- OnInitComplete
- OnPreLoad
- Page_Load
- OnLoad
- Button_Click
- OnLoadComplete
- OnPreRender
轉載于:https://www.cnblogs.com/wwkk/p/6606623.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的ASP.Net请求小周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC:学习笔记(10)——
- 下一篇: 2017春季华为实习生编程题