-
前言
百度了一下才知道,傳智的鄒老師桃李滿天下呀,我也是鄒老師的粉絲,最開始學習頁面生命周期的時候也是看了鄒老師的視頻。
本人是參考了以下前輩的作品,本文中也參合了本人心得,絕非有意盜版,旨在傳播,最主要是日后在下也可以參考一下,原版出處如下:
-
概念
所謂的頁面生命周期說通俗一點,就是瀏覽器有請求,服務器處理請求並生成HTML代碼所執行的一系列的事件方法。
-
概括知識點
1.服務器與瀏覽器之間的交互:通過Scoket
2.服務器與瀏覽器交互語法:Http協議
3.服務器與瀏覽器交互目的:獲取服務器資源(html,js,img,css..)
4.服務器要做的事就是想盡辦法滿足瀏覽器的需求,所以一旦瀏覽器請求的是動態頁面的時候,服務器就要創建頁面類對象並執行里面的一系列的事件與方法,並將生成的html頁面代碼返回給瀏覽器.
-
頁面生命周期事件
1.PreInit:
-
- 檢查IsPostBack 屬性
- 創建或重新創建動態控件
- 動態設置主控頁
- 動態設置Theme屬性
- 讀取或者設置配置文件屬性值
- 設置控件的默認值(UniqueId等)
- 動態設置Master Page
注意:如果請求是回發請求,剛控件的值尚未從視圖狀態還原,如果在此階段設置控件屬性,則其值可能會在下一事件中被重寫。
2. Init:
在所有控件都已經初始化且已應用所有外觀設置后引發,使用該事件來讀取或初始化控件屬性
3.InitComplete:
由Page對象引發。使用該事件來處理要求先完成所有初始化工作的任務。
4.PreLoad:
如果需要在Load事件之前對頁或者控件執行處理,則使用該事件。
在Page引發該事件后,它會為自身和所有 控件加載視圖狀態,然后會處理Request實例包括的任何回發數據。
5.Load:
在Page上調用OnLoad事件方法,然后以遞歸方式對每個子控件執行相同操作,如此循環往復,直到加載完頁面和所有控件為止
6.控件事件:
使用這些事件來處理特定控件事件,如Button控件的Click事件或TextBox控件的TextChanged事件
注意:在回發請求中,如果頁包含驗證程序控件,剛需要在執行任何處理之前檢查Page和各個驗證控件的IsValid屬性
7.LoadComplete:
對需要加載頁上的所有其他控件的任務使用該事件
8.PreRender:
在該事件發生之前:
-
- Page對象會針對每個控件和頁調用 EnsureChildControls
- 設置了DataSourceID屬性的每個數據綁定控件會調用DataBind方法
頁上的每個控件都會發生PreRender事件。使用該事件對頁或其控件的內容進行最后更改
9.SaveStateComplete
在該事件發生前,已對每個控件保存了ViewState。將忽略此時對頁或控件進行的任何更改。使用該事件執行滿足以下條件的任務:要求已經保存了視圖狀態,但未對控件進行任何更改。
10.Render
這不是事件:在處理的這個階段,Page對象會在每個控件上調用此方法。所有 ASP.NET Web服務器控件都有一個用於寫出發送給瀏覽器的控件標記的Render方法。如果創建自定義控件,則通常要重寫此方法以輸出控件的標記。不過如果自定義控件只合並標准的 ASP.NET Web服務器控件,並不合並自定義標記,則不需要重寫Render方法。用戶控件自動合並呈現,因此不需要在代碼中顯式呈現該控件。
11:UnLoad
該事件首先針對每個控件發生,繼而針對該頁發生,在控件中,使用該事件對特定控件執行最后清理,如關閉控件特定數據庫連接,清理輸出緩存。對於頁自,使用該事件來執行最后的清理工作,如關閉打開 的文件和數據庫連接,或完成日志記錄或其他特定請求任務。
-
學習目的
有些人講,webform/asp.net方面的技術,有些研究得太深,在現實開發中其實不一定有太大的價值。我極力的反駁這句話。據我個人了解與使用情況,學習頁面生命周期有以下幾個好處:
1.開發Asp.net自定義控件與用戶控件
2.利用HttpModule注冊頁面生命周期中HttpApplication中用於處理請求的19個事件管道所對外公布的一系列的事件方法
3.編寫頁面周期事件方法(如:Page_PreLoad,Page_Load,Page_Init...)等等一系列的事件,且這些方法並不會因為我們的編寫而覆蓋原有的事件方法,請大家放心使用,不過在上述所有事件前面要加上Page_。
-
注意事項
1.所有控件都有生命周期,我們在前面就已經了解到Page類是繼承Control類的,而我們所有的服務器控件也都是繼承Control類的
2.雖然Init與Load都在每個控件上以遞歸方式發生,但它們的發生順序相反,每個子控件的Init事件(還有UnLoad事件)在為其容器引發相應的事件之前發生(由上到下)。但是,容器的Load事件是在其子控件的Load事件之前 發生(由上到下)的。
3.從Page類繼承過來的時候,除了可以處理由頁引發的事件以外,還可以重寫頁的基類中的方法,例如可以重寫頁的InitializeCulture方法,以便動態設置區域性信息,注意,在使用Page_事件語法創建事件處理程序時,將隱式調用基實現,因此無須在方法中調用它。例如使用Page_Load方法始終會調用基類的OnLoad方法,如果使用overrider重寫了頁的OnLoad方法,則必須顯式調用基類的OnLoad方法,如base.OnLoad()以運行基實現。
-
瀏覽器與服務器的通信過程
通信過程:
當服務器運行正常的情況下,客戶端(瀏覽器) 向服務器端發送請求時,服務器端負責監聽的套接字(socket),監聽到有連接請求后,會為該客戶端建立一個用於通信的套接字與客戶端進行通信。當用戶在瀏覽器向服務器發送請求時,瀏覽器會按照雙方都約定好的網絡傳輸層http協議,將請求轉換成符合Http協議的請求報文。然后通過設備按照TCP協議發送到服務器。在服務器端接收到請求報文后。會按照Http協議對報文進行解析。若請求的內容為靜態的數據,服務器端直接將被請求的數據,按照Http協議生成響應報文后返回給瀏覽器。瀏覽器然后解析收到的報文。將頁面顯示到瀏覽器窗口。(注:最開始僅是顯示一個html 框架。經過多次請求。將CSS樣式,圖片………逐一的加載進來形成一個完整的頁面。這個過程,有多次的交互通信。當通信結束后會把用來通信的套接字銷毀,因為http協議是一種無狀態的通信。這樣減輕了服務器的壓力)
當瀏覽器向客戶端發送的請求為動態的。那么服務器(IIS)發現處理不了這種后綴名的文件時,會通過映射表到。響應實現了接口的可擴展程序asp.net_isapi.dll, 然后asp.net_isapi.dll,又將請求轉交給網站程序處理.網站程序調用
httpRuntime類的processRequest方法來處理:
1.此類會分析接收到的請求報文.將請求報文封裝到名稱為httpWorkerRequest的類的屬性中(便於其它地方以用).
2.創建HttpContext對象.這個對象是當前所請求報文的上下文環境.它包含了所有的請求數據.其中有兩個最重要類的對象:http.Request和http.Response. 在httpRequest對象中又包含了兩個屬性.Form(通過表單請求的數據參數).Querystring(通過URL傳遞的數據參數); 通過索引器,可以找到參數的值. 在httpResponse 對象中有一個TextWriter對象.在它里面保存的是被請求的頁面在執行過程中要向瀏覽器輸出的數據.可以通過write 方法對其進行輸出給瀏覽器。
3.通過HttpApplicationFactory類的的一個靜態方法。來為每個請求創建一個單獨的httpApplication對象。在創建之前HttpApplicationFactor會到HttpApplication池中查看,有沒有空閑的。若有直接用。沒有的時候才創建新的HttpApplication。
4.在httpApplication里運行己轉換成接口IhttpHandler 的通過反射被請求頁面對象的ProcessRequest 方法.
方法執行過程如下:先執行httpApplication中的processRequest方法。在此方法中包含了要按照先后順序執行的19個委托事件 當在執行到第8個事件(PostMapRequestHandler)的時候就開始創建被請求頁面對象,並得到請求處理程序,在執行到第11個事件(PreRequestHandlerExecute)后。就執行被創建的請求頁面對象的ProcessRequest方法。
-
HttpApplication 通信管理(用於給HttpModule注冊使用的19個事件委托)
HttpModule被稱為Filter過濾器。用戶可以利用HttpModule來給這19個委托事件來注冊方法,完成需求,比如說可以在AcquireRequestState中驗證是否登錄呀,權限驗證等
詳情請查看:HttpModule實現用戶身份驗證
如果不清楚HttpModule可以查看:HttpModule的認識
-
頁面生命周期詳細過程
其實頁面生命周期里面還有很東西,如PageHandlerFactory等等這些東東也夠吃一壺的,發現我每走到一個領域,發現我要學的東西實在是太多太多啦,總感覺自己所學的東西只是滄海一粟,走過了這道坎,又是一片海洋,我只能吶喊:生命永不止息,學海無涯。