zoukankan      html  css  js  c++  java
  • 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的实例,而该实例中又包含以下属性:

     

    注1

    Application -->相当于传统意义上asp时代的application对象,通常用于定义一个asp.net应用的全局变量

    Context -->HttpContext(上下文)类的实例【Asp.Net新增的】

    Modules -->影响当前应用程序的HttpModule模块集合

    Request -->类似于asp中的Request对象,通常用于接收一些特定的值(比如Request.Form或Request.QueryString)

    Response -->类似于asp中的Response对象,通常用于向做页面输出指定内容(比如Resonse.Write)

    Server -->类似于asp中的Server对象,通过它能获得一些服务端的信息(比如Server.MapPath)

    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的)

    1
    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...等对象的实例引用


    回想一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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对象感到很熟悉,比如:

    1
    2
    3
    4
    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页面生命周期的权威解释

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

    文中测试所用的源代码: https://files.cnblogs.com/yjmyzz/aspx_life_test.rar (用vs2010 RC打开)

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    第一节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
    Tensorflow 错误:Unknown command line flag 'f'
    Python 多线程总结
    Git 强制拉取覆盖本地所有文件
    Hive常用函数 傻瓜学习笔记 附完整示例
    Linux 删除指定大小(范围)的文件
    Python 操作 HBase —— Trift Trift2 Happybase 安装使用
    梯度消失 梯度爆炸 梯度偏置 梯度饱和 梯度死亡 文献收藏
    Embedding 文献收藏
    深度学习在CTR预估中的应用 文献收藏
  • 原文地址:https://www.cnblogs.com/wsion/p/2920895.html
Copyright © 2011-2022 走看看