ASP.NET管线与应用程序生命周期

原创 2008年10月03日 10:56:00
ASP.NET Web编程原理 之 

8.2 ASP.NET管线与应用程序生命周期

       8.1节介绍了IIS的系统架构和HTTP请求处理的总体流程,从中可以知道每个ASP.NET网站都对应着一个Web应用程序,此Web应用程序可以响应HTTP请求,为用户提供所需的信息。那么,ASP.NET应用程序具体是如何响应HTTP请求的?包括哪些具体的处理流程?这涉及到ASP.NET应用程序的生命周期问题。

8.2.1 ASP.NET应用程序生命周期*

       本节以IIS 6为例分步介绍ASP.NET应用程序处理HTTP请求的处理流程。IIS 7的处理过程与IIS 6相比有些小变化,但总体上是一致的。

1 浏览器发出访问某ASP.NET网页的HTTP请求

       假设这个请求是针对此网页所属的ASP.NET应用程序的第一次请求。

       当此请求到达Web服务器时,由HTTP.SYS负责接收,根据此请求的URLHTTP.SYS将其传递给此ASP.NET应用程序所对应的应用程序池,由在此应用程序池中运行的工作者进程负责处理请求[1]

       工作者进程接收到这个请求之后,装载专用于处理ASP.NET页面的一个ISAPI扩展“aspnet_isapi.dll”,并将HTTP请求传给它。

       工作者进程加载完aspnet_isapi.dll后,由aspnet_isapi.dll负责加载ASP.NET应用程序的运行环境――CLR[2]。 

       工作者进程工作于非托管环境(指Windows操作系统本身)之中,而.NET中的对象则工作于托管环境(指CLR)之中,aspnet_isapi.dll起到了一个沟通两者的桥梁作用,将收到的HTTP请求(由非托管环境传来)转发给相应.NET对象(处于托管环境中)处理。

2 创建ApplicationManager对象和应用程序域

       加载CLR之后,由ApplicationManager类负责创建一个应用程序域。每个ASP.NET应用程序都运行于自己的应用程序域中,由唯一的应用程序标识符标识。

       每个应用程序域都对应着一个ApplicationManager类的实例,由它来负责管理运行在域中的ASP.NET应用程序(比如启动和停止一个ASP.NET应用程序,在指定的ASP.NET应用程序中创建对象等等)。

3 创建HostingEnvironment对象

       在为ASP.NET应用程序创建应用程序域的同时,会创建一个HostingEnvironment对象,此对象提供了ASP.NET应用程序的一些管理信息(比如ASP.NET应用程序的标识,对应的虚拟目录和物理目录),并提供了一些附加的功能(比如在应用程序域中注册一个对象,模拟特定的用户等等)。

4为每个请求创建 ASP.NET 核心对象

       当应用程序域创建完成之后,一个ISAPIRuntime对象被创建,并自动调用它的ProcessRequest()方法。在此方法中,ISAPIRuntime对象根据传入的HTTP请求创建一个HttpWorkerRequest对象,此对象以面向对象的方式包装了HTTP请求的各种信息(这就是说,原始的HTTP请求信息被封装为HttpWorkerRequest对象)。然后,调用ISAPIRuntime对象的StartProcessing()方法启动整个HTTP请求处理过程(此即“HTTP管线:HTTP Pipeline),在这个处理过程的开端,一个HttpRuntime类型的对象被创建,前面创建好的HttpWorkerRequest对象作为方法参数被传送给此HttpRuntime对象的ProcessRequest()方法。

       HttpRuntime类的ProcessRequest()方法中完成了一些非常重要的工作,其中与Web软件工程师关系最紧密的是:

HttpRuntime类的ProcessRequest()方法根据HttpWorkerRequest对象中所提供的HTTP请求信息,创建了一个HttpContext对象。

       HttpContext对象之所以重要,是因为此对象包容了另两个在ASP.NET编程中非常常见的对象:HttpResponseHttpRequest

       HttpRequest对象中的信息来自于原始的HTTP请求,比如它的Url属性就代表了原始HTTP请求信息中的URL

       HttpResponse对象则拥有一些属性和方法,用于生成要返回给浏览器的信息。

       Page类提供了相应的属性来引用这两个对象,因此在ASP.NET网页中可以直接使用“Requset”和“Response”属性来访问这两个对象。例如:

 

    public partial class _Default : System.Web.UI.Page

    {

         protected void Page_Load(object sender, EventArgs e)

         {

            Response.Write(Request.Url);

         }

    }

 

       Page类的Context属性引用HttpContext对象,因此,上述代码也可以改写为以下形式:

 

    public partial class _Default : System.Web.UI.Page

    {

         protected void Page_Load(object sender, EventArgs e)

         {

              this.Context.Response.Write(this.Context.Request.Url);

         }

    }

 

       关于HttpContextHttpResponseHttpRequest这三个对象,必须掌握以下的要点:

l  HttpContext对象包容HttpResponseHttpRequest这两个对象,可以从HttpRequest对象获取HTTP请求的相关信息,而要向浏览器输出的内容可以通过调用HttpResponse的方法实现。

l  针对每个HTTP请求,ASP.NET都会创建一个HttpContext对象,在整个HTTP处理过程中,此对象都是可以访问的。

5 分配一个HttpApplication 对象用于处理请求

       HttpRuntime类的ProcessRequest()方法除了创建HttpContext对象之外,还完成了另一个很重要的工作——向HttpApplicationFactory类的一个实例[3]申请分配一个HttpApplication 对象用于管理整个HTTP请求处理管线中的各种事件。

       HttpApplicationFactory对象负责管理一个HttpApplication对象池[4],当有HTTP请求到来时,如果池中还有可用的 HttpApplication对象,就直接分配此对象用于处理HTTP请求,否则,创建一个新的HttpApplication对象。

6 HttpApplication对象启动HTTP管线

       HttpApplication对象负责装配出整个“HTTP请求处理管线(HTTP Pipeline”,可以将“HTTP请求处理管线”与现代工厂中的“生产流水线”做个类比。前面步骤中创建好的HttpContext对象就是这个生产流水线要加工的“产品”,当它流经“生产流水线”的不同部分时,将被进行特定的加工和处理过程。

       这些特定的“加工和处理过程”是怎样进行的?

       简单地说,HttpContext对象经过“生产流水线”的不同部分时,HttpApplication对象会先后激发出一连串的事件[5]。一种特定的组件——HTTP模块(HTTP Module)可以响应这些事件,在此事件响应代码中可以对HttpContext对象进行“加工和处理”,从这个意义上说,HTTP模块可以看成是“生产流水线”中的工人。HTTP模块其实就是前面所介绍过的“ISAPI筛选器”。

       HTTP模块对象是在HttpApplication对象的InitModules()方法[6]中被创建的,我们一般在HTTP模块对象Init()方法[7]中书写代码使其可以响应HttpApplication对象所激发的特定事件。

       ASP.NET提供了一些预定义的HTTP模块响应特定的事件,Web软件工程师也可以编写自己的HTTP模块并将其插入到“HTTP请求处理管线”中[8]

       在流水线的中部(处理完了相关的事件),HttpContext对象被最终的Page对象所接收(这就是为何可以在ASP.NET页面中通过Page类定义的Context属性访问HttpContext对象的原因)。

       每个被访问的ASP.NET页面都会被转换为一个“派生自Page类的页面类

       注意:Page类实现了IHttpHandler接口,此接口定义了一个ProcessRequest()方法。

       ASP.NET页面类生成以后被自动编译为程序集,然后其ProcessRequest()方法被自动调用(因为Page类实现了IHttpHandler接口,所以肯定有此方法)。在此方法中,Web软件工程师编写的代码被执行(如果有的话)。ProcessRequest()方法的执行结果再次被HttpContext对象所承载,控制又转回到“HTTP请求处理流水线”中,HttpApplication对象继续激发后继的事件。这时,如果还有特定的HTTP模块响应这些事件,则它们会被自动调用。

       HttpContext对象带着最后的处理结果来到了“HTTP请求处理管线”的未端,其信息被取出来,再次以aspnet_isapi.dll为桥梁传送给工作者进程。工作者进程再将HTTP请求的处理结果转给HTTP.SYS,由它负责将结果返回给浏览器。

       根据前面的介绍,可以将整个Http管线分成三段:预处理阶段à处理阶段à后处理阶段 814)。

 

HTTP Pipeline 814 HTTP管线的三个阶段

 

       814所示,HTTP管线的预处理和后处理阶段主要由多个HTTP模块参与,通过事件来驱动,这两个阶段完成的工作主要是对HttpContext对象的各种属性进行修改。

       HTTP请求的处理过程最终是由一个实现IHttpHandler接口的对象在“处理阶段”完成的。每一个ASP.NET网页生成的页面类都实现了此接口。创建出合适的HTTP请求处理对象的工作由PageHandlerFactory对象[9]负责完成。

       由此可见,实现了IHttpHandler接口的对象负责处理HTTP请求,这就是它被称为“Handler(处理程序)”的原因。

       除了最常见的ASP.NET网页之外,Web软件工程师还可以创建自己的实现了IHttpHandler接口的对象,并将其插入到HTTP管线中用于处理HTTP请求。

       HTTP请求处理完毕,相关的对象被释放,但创建的应用程序域,以及HttpApplication等对象仍然存活,以响应下一次HTTP请求。

7 ASP.NET应用程序生命周期小结

       本节中介绍了ASP.NET应用程序的生命周期,这是一个相当复杂的过程,也许用以下通俗的类比更容易理解:

l  HTTP请求处理管线”就是一条现代工厂中的“生产流水线”,HttpContext对象就是这条流水线上要加工的产品。

l  HttpHandlerHTTP处理程序)对象是整个“产品生产线”的核心,由它负责将产品装配成形。

l  HttpModuleHTTP模块)相当于“生产线”上的辅助工人,他们对产品(HttpContext对象)进行“预处理”(为装配产品作准备)和“后处理”(为产品出厂作准备,比如贴商标)。

l  HttpApplication对象是整个“生产线”的“领导” ,他负责给“生产线”分配工人(初始化并装载所有注册的HttpModule),然后会激发一系列的事件(被称为“ASP.NET应用程序事件”),特定的HttpModule负责响应特定的事件。



[1] 如果工作者进程不存在,则IIS监控程序WAS会创建一个,否则,复用已有的工作者进程。

[2] IIS 7集成模式下,由于CLR是预加载的,所以这一步就不需要了。

[3] “类的实例”与“类的对象”含义等同,都是指以类为模板创建出来的对象。

[4] 对象池(object pool)是面向对象软件系统常见的一种对象组织方式,可以将其看成是一个对象容器。对象池中放有事先创建好的多个对象。当外界需要某个对象时,可以直接从池中取出一个现成的对象使用,这就避免了频繁创建对象所带来的性能损失。

[5] HttpApplication定义了相当多的事件,完整的事件清单请查看MSDN

[6] 此方法会在获取HttpApplication对象时被自动调用。

[7] 所有HTTP模块都要实现IHttpModule接口,Init()方法由此接口所定义。

[8] 通过在Web.Config中插入特定的内容可以将自定义的HTTP模块加入到HTTP请求的处理流程中。

[9] 这是ASP.NET技术框架中的另一个核心类。

 

*******************************************

本系列文章结束语:

理解Http PipeLine在ASP.NET编程中有着重要的意义,只有对它有所了解,才能理解开发中遇到的种种问题,并为学习和掌握更复杂的Web开发技术(比如自定义HttpModule和HttpHandler)打下基础。

到此为止,有关ASP.NET Web编程原理的系列文章就贴完了。之所以只贴这部分,是因为我发现许多ASP.NET技术书籍对这一部分内容都语焉不详,一带而过,而这一部分又是非常重要的,期望这四篇文章能对大家有所帮助。其他的常规内容绝大多数ASP.NET技术书籍都有,就不再赘述了。

本文如有错误及疏漏之处,也恳求高手指出。

祝大家学习顺利。

 

 

                          金旭亮

                         2008年国庆于北京

 

ASP.NET管线与应用程序生命周期

ASP.NET Web编程原理 之  8.2 ASP.NET管线与应用程序生命周期        8.1节介绍了IIS的系统架构和HTTP请求处理的总体流程,从中可以知道每个ASP.NET网站都对...
  • wawalike
  • wawalike
  • 2015年02月12日 17:31
  • 144

Asp.Net底层解析(四)——应用程序生命周期与HttpModule

前言:一般ASP.NET开发者对页面生命周期(PageLife Cycle)是比较熟悉的,在开发ASP.NET应用程序中经常需要从页面周期的角度去思考问题。实际上在页面生命周期的背后,还存在着一个不太...
  • mlcactus
  • mlcactus
  • 2013年02月01日 23:21
  • 1756

asp.net MVC 应用程序的生命周期

首先我们知道http是一种无状态的请求,他的生命周期就是从客户端浏览器发出请求开始,到得到响应结束。那么MVC应用程序从发出请求到获得响应,都做了些什么呢?       本文我们会详细讨论MVC...
  • letmefish
  • letmefish
  • 2016年08月10日 17:08
  • 976

ASP.NET生命周期详解

最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等...
  • sundacheng1989
  • sundacheng1989
  • 2013年08月28日 19:18
  • 11746

Android 应用程序生命周期

今天突然就bu'xia啊,接下来了解下Service
  • zqingyang521
  • zqingyang521
  • 2014年10月29日 13:56
  • 434

Asp.Net底层解析(三)——ASPX页面的生命周期详解

前言:个人认为,对于页面生命周期的理解是开发人员在ASP.NET领域做好做深的前提。当然,因为微软已经将ASP.NET封装得很简单了,所以对于只有基本html&javascript的初学者来说也很容易...
  • mlcactus
  • mlcactus
  • 2013年02月01日 23:21
  • 2476

详解ASP.NET MVC的请求生命周期

本文的目的旨在详细描述ASP.NET MVC请求从开始到结束的每一个过程。我希望能理解在浏览器输入URL并敲击回车来请求一个ASP.NET MVC网站的页面之后发生的任何事情。 为什么需要关心这...
  • edison0621
  • edison0621
  • 2014年06月30日 09:38
  • 3364

asp.net web 页面生命周期

每次客户端请求都会创建页面实例,它的执行使自身及其包含的控件经历页面生命周期的各个阶段。页面的执行起始于HTTP运行库调用ProcessRequest时,该方法将启动页面并控制它的生命周期。生命周期由...
  • lqh4188
  • lqh4188
  • 2013年01月23日 15:06
  • 2033

ASP.NET 应用程序生命周期和ASP.NET 页生命周期

先来两篇官方文章: ASP.NET 应用程序生命周期概述 ASP.NET 页生命周期概述 下面是一篇通俗易懂的文章,讲解可能有些许错误,请以官方文档为准。转自点击打开链接 在本文中,我们将...
  • MkCrawling
  • MkCrawling
  • 2015年09月28日 15:19
  • 395

ASP.NET中服务器控件的生命周期

服务器控件的生命周期是创建服务器控件最重要的概念。作为开发人员,必须对服务器控件生命周期深刻理解。当然,这不是一朝一夕就可以做到的。对于学习控件开发技术的初学者,可以不必掌握得非常详细深入,只需对服务...
  • bigpudding24
  • bigpudding24
  • 2015年10月28日 21:25
  • 797
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ASP.NET管线与应用程序生命周期
举报原因:
原因补充:

(最多只允许输入30个字)