HttpApplication,HttpModule,HttpContext及Asp.Net頁生命週期

IIS在接到一個新的http請求後,最終會調用asp.net_isapi.dll的ISAPI擴展(特指IIS6.0環境,iis7.0的應用程序池默認爲集成方式,相對有所變化),而後傳遞到httpRuntime Pipe(http運行時管道),Asp.Net這時纔開始運行(即HttpRunTime是Asp.Net真正的入口),HttpRunTime會爲每一個asp.net應用自動建立一個HttpApplication的實例,而該實例中又包含如下屬性:html

注1web

Application -->至關於傳統意義上asp時代的application對象,一般用於定義一個asp.net應用的全局變量api

Context -->HttpContext(上下文)類的實例【Asp.Net新增的】緩存

Modules -->影響當前應用程序的HttpModule模塊集合安全

Request -->相似於asp中的Request對象,一般用於接收一些特定的值(好比Request.Form或Request.QueryString)併發

Response -->相似於asp中的Response對象,一般用於向作頁面輸出指定內容(好比Resonse.Write)app

Server -->相似於asp中的Server對象,經過它能得到一些服務端的信息(好比Server.MapPath)asp.net

Session -->相似於asp中的Session對象函數

User -->用於獲取用戶認證相關的安全信息高併發

從上面的屬性能夠發現:不少其實在asp年代已在使用,只有Context,Modules,User這三個是Asp.Net新增的

HttpApplication類除了具有"注1"的幾個屬性外,還有本身的方法,這裏特別提一下Init方法和Dispose方法,這二個方法都可重載.

它們的調用時機爲:

Init方法在Application_Start以後調用,而Dispose在Application_End以前調用,另外Application_Start在整個asp.net應用的生命週期內只激發一次(好比IIS啓動或網站啓動時),相似的Application_End也只有當asp.net應用程序關閉時被調用(好比IIS中止或網站中止時)

除了Application_Start和Application_End方法,HttpApplication還提供瞭如下事件:

這些事件包括前面提到的可重載的Init及Dispose方法,再加上Session對應的Session_Start與Session_End方法,都可直接在Global.ascx.cs中以Application_XXX的形式使用(由於Global.ascx.cs中定義的類Global自己就是繼承自HttpApplication的)

public class Global : System.Web.HttpApplication

再來看一下相對asp而言,新增的Context,Modules,User這三個屬性

Context:

Context即HttpContext類的實例,在幾乎整個aspx頁面生命週期中,Context上下文一直伴隨着各個環節向下傳遞

因此咱們幾乎能夠在web應用中的任何環節,用HttpContext.Current來引用到當前的上下文實例,從HttpContext的定義上,還能夠發現Context自己的屬性中,又能夠獲得Application,ApplicationInstance,Profile,Response.Request...等對象的實例引用


回想一下:

public class Handler1 : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

咱們在使用一個ashx文件時,ProcessRequest方法即是把當前上下文傳遞進來,進而經過context獲得Response對象的引用,最終能夠向頁面輸出任何想要的內容.

Modules:

每個實現了IHttpModule接口的類,就能夠被認爲是Http模塊組件,能夠理解爲http請求攔截器,攔截到http請求後,它能修改正在被處理的Context上下文,完事兒以後,再把控制權交還給管道,若是還有其它模塊,則依次繼續處理,直到全部Modules集合中的HttpModule都「爽」完爲止(注:可憐的http請求就這樣給各個httpModule輪X了)

asp.net2.0默認內置了不少HttpModule,從Machine.Config文件中能夠發現如下默認的內置模塊:

注2
AnonymouseIdentification --爲匿名用戶分配一個臨時身份
FileAuthorization --驗證用戶是否有請求文件的Windows NT許可
FormsAuthentication --窗體身份驗證模塊(若是沒有這個模塊,asp.net就沒法以用戶名/密碼[即FOrms]方式驗證)
OutputCache --輸出緩存模塊
PassportAuthentication --PassPort驗證模塊
Profile --用戶配置模塊(若是沒有它,asp.net中就沒法使用Profile)
RoleManager --角色管理
SessionSate --會話狀態模塊
UrlAuthorization --基於URL的身份驗證模塊
WindowsAuthentication --Windows和IIS身份驗證模塊

User:

若是您使用過asp.net2.0內置的Membership/Role機制來進行訪問認證,就會對User對象感到很熟悉,好比:

if (HttpContext.Current.User.Identity.IsAuthenticated) 
{
     //用戶登陸過了...
}


咱們經常使用它來判斷當前瀏覽用戶的登陸狀態,關於User類的更詳細定義,可參見MSDN


生命週期:

最後再來回顧一下Asp.Net中Page頁的生命週期,Page中定義了幾個事件:

整體上講:一個ASPX頁面被請求時,最終的生命週期就是由Page中定義的上述事件(還有一些可重載的回調方法)以及之前提到的HttpApplication類中定義的事件(以相應的回調方法)共同觸發或調用,最終疊加造成的一連串處理過程。

若是先不考慮HttpApplication中的事件處理方法(即不考慮咱們在Global.ascx.cs中定義的Application_XXX處理方法),Page中的事件(方法)常規觸發(調用)順序爲:

01.Page_PreInit

02.Page_Init

03.Page_InitComplete

04.Page_PreLoad

05.Page_Load

06.Page_LoadComplete

07.Page_PreRender

08.Page_SaveStateComplete

09.Page_Unload

這是在Page頁面未回發,且不考慮頁面子控件的前提下正常的順序,若是加入頁面回發(好比在頁面中放一個asp:Button,而後在Button的Click回發事件中加入處理函數)後,順序稍微有些變化:

01.Page_PreInit

02.Page_Init

03.Page_InitComplete

04.Page_PreLoad

05.Page_Load

06.Button1_Click

07.Page_LoadComplete

08.Page_PreRender

09.Page_SaveStateComplete

10.Page_Unload

不一樣的地方在於:回發事件Button1_Click在Page_Load後被觸發.

最後再把HttpApplication的事件考慮進來,看下疊加後的順序,不過先彆着急,咱們先來看一種特殊狀況,若是一個asp.net應用根目錄下未設置默認頁,這時直接瀏覽根目錄,好比http://localhost:2345/ 時,Globl.ascx.cs中定義的Application_XXX方法的調用順序以下:
2010-03-28 15:01:39 413 Application_Start
2010-03-28 15:01:39 491 Init
2010-03-28 15:01:39 491 Application_BeginRequest
2010-03-28 15:01:39 506 Application_AuthenticateRequest
2010-03-28 15:01:39 506 Application_PostAuthenticateRequest
2010-03-28 15:01:39 506 Application_AuthorizeRequest
2010-03-28 15:01:39 522 Application_PostAuthorizeRequest
2010-03-28 15:01:39 522 Application_ResolveRequestCache
2010-03-28 15:01:39 522 Application_PostResolveRequestCache
2010-03-28 15:01:39 522 Application_PostMapRequestHandler
2010-03-28 15:01:39 522 Application_AcquireRequestState
2010-03-28 15:01:39 537 Application_PostAcquireRequestState
2010-03-28 15:01:39 537 Application_PreRequestHandlerExecute
2010-03-28 15:01:39 553 Application_Error
2010-03-28 15:01:39 553 Application_EndRequest
2010-03-28 15:01:39 569 Application_PreSendRequestHeaders
2010-03-28 15:01:39 569 Application_PreSendRequestContent

能夠看到會觸發Application_Error事件,即HttpRuntime認爲這是一個錯誤.

緊接着再瀏覽一個實際存在的頁面,若是這時應用程序有嚴重錯誤,致使Application關閉(好比web.config配置錯誤),調用的順序以下:
2010-03-28 15:03:47 704 Application_BeginRequest
2010-03-28 15:03:47 704 Application_AuthenticateRequest
2010-03-28 15:03:47 766 Application_PostAuthenticateRequest
2010-03-28 15:03:47 766 Application_AuthorizeRequest
2010-03-28 15:03:47 766 Application_PostAuthorizeRequest
2010-03-28 15:03:47 766 Application_ResolveRequestCache
2010-03-28 15:03:47 783 Application_PostResolveRequestCache
2010-03-28 15:03:48 667 Application_PostMapRequestHandler
2010-03-28 15:03:48 667 Application_AcquireRequestState
2010-03-28 15:03:48 683 Application_PostAcquireRequestState
2010-03-28 15:03:48 698 Application_PreRequestHandlerExecute
2010-03-28 15:03:48 745 Page_PreInit
2010-03-28 15:04:02 903 Page_Unload
2010-03-28 15:04:02 903 Application_Error
2010-03-28 15:04:02 918 Application_EndRequest
2010-03-28 15:04:02 996 Application_PreSendRequestHeaders
2010-03-28 15:04:02 996 Application_PreSendRequestContent
2010-03-28 15:04:03 371 Application_Disposed
2010-03-28 15:04:03 371 Dispose
2010-03-28 15:04:03 386 Application_End

對比剛纔的順序,會發現Application_Start及Init沒有再次被調用,也印證了文章前面提到的一些結論(Application_Start在整個asp.net應用生命週期內只觸發一次),並且從最後的三個輸出能知道:應用程序關閉時Application_Disposed,Dispose,Application_End按順序調用.

再"從新"瀏覽(指web Server重啓)一下正常訪問的頁面,在不出錯也不回發的狀況下,順序以下:
2010-03-28 15:08:11 513 Application_Start
2010-03-28 15:08:11 591 Init
2010-03-28 15:08:11 591 Application_BeginRequest
2010-03-28 15:08:11 591 Application_AuthenticateRequest
2010-03-28 15:08:11 591 Application_PostAuthenticateRequest
2010-03-28 15:08:11 606 Application_AuthorizeRequest
2010-03-28 15:08:11 606 Application_PostAuthorizeRequest
2010-03-28 15:08:11 606 Application_ResolveRequestCache
2010-03-28 15:08:11 606 Application_PostResolveRequestCache
2010-03-28 15:08:11 622 Application_PostMapRequestHandler
2010-03-28 15:08:11 637 Application_EndRequest
2010-03-28 15:08:11 637 Application_PreSendRequestHeaders
2010-03-28 15:08:11 637 Application_PreSendRequestContent
2010-03-28 15:08:11 637 Application_BeginRequest
2010-03-28 15:08:11 637 Application_AuthenticateRequest
2010-03-28 15:08:11 653 Application_PostAuthenticateRequest
2010-03-28 15:08:11 653 Application_AuthorizeRequest
2010-03-28 15:08:11 653 Application_PostAuthorizeRequest
2010-03-28 15:08:11 653 Application_ResolveRequestCache
2010-03-28 15:08:11 653 Application_PostResolveRequestCache
2010-03-28 15:08:11 653 Application_PostMapRequestHandler
2010-03-28 15:08:11 653 Session_Start
2010-03-28 15:08:11 653 Application_AcquireRequestState
2010-03-28 15:08:11 653 Application_PostAcquireRequestState
2010-03-28 15:08:11 653 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 669 Page_PreInit
2010-03-28 15:08:11 684 Page_Init
2010-03-28 15:08:11 684 Page_InitComplete
2010-03-28 15:08:11 684 Page_PreLoad
2010-03-28 15:08:11 684 Page_Load
2010-03-28 15:08:11 684 Page_LoadComplete
2010-03-28 15:08:11 684 Page_PreRender
2010-03-28 15:08:11 684 Page_SaveStateComplete
2010-03-28 15:08:11 700 Page_Unload
2010-03-28 15:08:11 700 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 700 Application_ReleaseRequestState
2010-03-28 15:08:11 700 Application_PostReleaseRequestState
2010-03-28 15:08:11 700 Application_UpdateRequestCache
2010-03-28 15:08:11 700 Application_PostUpdateRequestCache
2010-03-28 15:08:11 700 Application_EndRequest
2010-03-28 15:08:11 700 Application_PreSendRequestHeaders
2010-03-28 15:08:11 700 Application_PreSendRequestContent
2010-03-28 15:08:11 793 Application_BeginRequest
2010-03-28 15:08:11 793 Application_AuthenticateRequest
2010-03-28 15:08:11 793 Application_PostAuthenticateRequest
2010-03-28 15:08:11 793 Application_AuthorizeRequest
2010-03-28 15:08:11 793 Application_PostAuthorizeRequest
2010-03-28 15:08:11 793 Application_ResolveRequestCache
2010-03-28 15:08:11 793 Application_PostResolveRequestCache
2010-03-28 15:08:11 809 Application_PostMapRequestHandler
2010-03-28 15:08:11 809 Application_AcquireRequestState
2010-03-28 15:08:11 809 Application_PostAcquireRequestState
2010-03-28 15:08:11 809 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 825 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 825 Application_ReleaseRequestState
2010-03-28 15:08:11 840 Application_PostReleaseRequestState
2010-03-28 15:08:11 949 Application_UpdateRequestCache
2010-03-28 15:08:11 949 Application_PostUpdateRequestCache
2010-03-28 15:08:11 965 Application_EndRequest
2010-03-28 15:08:11 981 Application_PreSendRequestHeaders
2010-03-28 15:08:11 981 Application_PreSendRequestContent

哇!原來一個頁面訪問下來,會調用到這麼多的方法,怪不得不少高併發的大型網站,一般都要本身寫一個精減的HttpHandler用來取代Page作爲基類,以指望得到更好的性能

最後:咱們在作網站開發時,不可能只用到Page頁,不少時候還會用到UserControl(用戶自定義控件),先看下它的繼承關係,好比咱們建立了一個TestUserControl的用戶控件

TestUserControl --> UserControl ---> TemplateControl --> Control

最終在Control類的定義下,能夠看到

這彷佛代表用戶控件中,應該有Page_Init,Page_Load,Page_Unload...等事件,一般咱們只用到Init,Load事件,若是加入一個用戶控件後,整個生命週期就更復雜了:

2010-06-12 15:35:28 042 Application_Start
2010-06-12 15:35:28 072 Init
2010-06-12 15:35:28 072 Application_BeginRequest
2010-06-12 15:35:28 082 Application_AuthenticateRequest
2010-06-12 15:35:28 082 Application_PostAuthenticateRequest
2010-06-12 15:35:28 092 Application_AuthorizeRequest
2010-06-12 15:35:28 102 Application_PostAuthorizeRequest
2010-06-12 15:35:28 102 Application_ResolveRequestCache
2010-06-12 15:35:28 112 Application_PostResolveRequestCache
2010-06-12 15:35:28 122 Application_PostMapRequestHandler
2010-06-12 15:35:28 142 Application_EndRequest
2010-06-12 15:35:28 142 Application_PreSendRequestHeaders
2010-06-12 15:35:28 142 Application_PreSendRequestContent
2010-06-12 15:35:28 152 Application_BeginRequest
2010-06-12 15:35:28 152 Application_AuthenticateRequest
2010-06-12 15:35:28 162 Application_PostAuthenticateRequest
2010-06-12 15:35:28 162 Application_AuthorizeRequest
2010-06-12 15:35:28 162 Application_PostAuthorizeRequest
2010-06-12 15:35:28 172 Application_ResolveRequestCache
2010-06-12 15:35:28 172 Application_PostResolveRequestCache
2010-06-12 15:35:28 172 Application_PostMapRequestHandler
2010-06-12 15:35:28 172 Session_Start
2010-06-12 15:35:28 172 Application_AcquireRequestState
2010-06-12 15:35:28 182 Application_PostAcquireRequestState
2010-06-12 15:35:28 182 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 192 Page_PreInit
2010-06-12 15:35:28 192 TestUserControl.Page_Init
2010-06-12 15:35:28 202 Page_Init
2010-06-12 15:35:28 202 TestUserControl.TestProperty.Set
2010-06-12 15:35:28 202 Page_InitComplete
2010-06-12 15:35:28 202 Page_PreLoad
2010-06-12 15:35:28 202 Page_Load
2010-06-12 15:35:28 202 TestUserControl.Page_Load
2010-06-12 15:35:28 202 TestUserControl.ShowData()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 Page_LoadComplete
2010-06-12 15:35:28 232 Page_PreRender
2010-06-12 15:35:28 232 TestUserControl.Page_PreRender
2010-06-12 15:35:28 242 Page_SaveStateComplete
2010-06-12 15:35:28 242 TestUserControl.Page_Unload
2010-06-12 15:35:28 252 Page_Unload
2010-06-12 15:35:28 252 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 252 Application_ReleaseRequestState
2010-06-12 15:35:28 252 Application_PostReleaseRequestState
2010-06-12 15:35:28 262 Application_UpdateRequestCache
2010-06-12 15:35:28 262 Application_PostUpdateRequestCache
2010-06-12 15:35:28 262 Application_EndRequest
2010-06-12 15:35:28 272 Application_PreSendRequestHeaders
2010-06-12 15:35:28 272 Application_PreSendRequestContent
2010-06-12 15:35:28 282 Application_BeginRequest
2010-06-12 15:35:28 292 Application_AuthenticateRequest
2010-06-12 15:35:28 292 Application_PostAuthenticateRequest
2010-06-12 15:35:28 302 Application_AuthorizeRequest
2010-06-12 15:35:28 302 Application_PostAuthorizeRequest
2010-06-12 15:35:28 302 Application_ResolveRequestCache
2010-06-12 15:35:28 312 Application_PostResolveRequestCache
2010-06-12 15:35:28 312 Application_PostMapRequestHandler
2010-06-12 15:35:28 322 Application_AcquireRequestState
2010-06-12 15:35:28 322 Application_PostAcquireRequestState
2010-06-12 15:35:28 322 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 332 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 332 Application_ReleaseRequestState
2010-06-12 15:35:28 332 Application_PostReleaseRequestState
2010-06-12 15:35:28 342 Application_UpdateRequestCache
2010-06-12 15:35:28 342 Application_PostUpdateRequestCache
2010-06-12 15:35:28 342 Application_EndRequest
2010-06-12 15:35:28 342 Application_PreSendRequestHeaders
2010-06-12 15:35:28 342 Application_PreSendRequestContent
2010-06-12 15:36:40 034 Session_End

 

更準確的頁面生命週期解釋,請查閱下面的文檔,這是msdn官方網站對於Asp.Net頁面生命週期的權威解釋

http://files.cnblogs.com/yjmyzz/Asp.Net-Page-Life.rar


出處:http://yjmyzz.cnblogs.com/

相關文章
相關標籤/搜索