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

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

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负责接收,根据此请求的URL,HTTP.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编程中非常常见的对象:HttpResponse和HttpRequest

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

}

}

关于HttpContext、HttpResponse和HttpRequest这三个对象,必须掌握以下的要点:

l  HttpContext对象包容HttpResponse和HttpRequest这两个对象,可以从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管线分成三段:预处理阶段à处理阶段à后处理阶段(图8?14)。

图 8?14 HTTP管线的三个阶段

如图 8?14所示,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  HttpHandler(HTTP处理程序)对象是整个“产品生产线”的核心,由它负责将产品装配成形。

l  HttpModule(HTTP模块)相当于“生产线”上的辅助工人,他们对产品(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技术书籍都有,就不再赘述了。

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

祝大家学习顺利。

时间: 2024-12-17 23:12:04

ASP.NET管线与应用程序生命周期的相关文章

asp.net应用程序生命周期和asp.net网页的生命周期

一.asp.net应用程序生命周期 asp.net应用程序生命周期以浏览器向web服务器(比如IIS服务器)发送请求为起点,先后经历web服务器下的ISAPI(Internet Server Application Programming Interface)扩展接收到应用程序的第一个请求并创建一个应用程序域,为每个请求创建ASP.NET核心对象(如HttpContext.HttpRequest.HttpResponse),将HttpApplication对象分配给请求(即通过创建HttpApp

IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述

本主题概述 ASP.NET 应用程序的生命周期,列出了重要的生命周期事件,并描述了您编写的代码将如何适应于应用程序生命周期.本主题中的信息适用于 IIS 5.0 和 IIS 6.0.有关 IIS 7.0 中的 ASP.NET 应用程序生命周期的信息,请参见 IIS 7.0 的 ASP.NET 应用程序生命周期概述. 在 ASP.NET 中,若要对 ASP.NET 应用程序进行初始化并使它处理请求,必须执行一些处理步骤. 此外,ASP.NET 只是对浏览器发出的请求进行处理的 Web 服务器结构的

IIS 7.0 的 ASP.NET 应用程序生命周期概述(转载)

IIS 7.0 的 ASP.NET 应用程序生命周期概述更新:2007 年 11 月本主题介绍在 IIS 7.0 集成模式下运行以及与 IIS 7.0 或更高版本一起运行的 ASP.NET 应用程序的应用程序生命周期.IIS 7.0 还支持经典模式,其行为类似于在 IIS 6.0 中运行的 ASP.NET.有关更多信息,请参见 IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述.IIS 7.0 集成管道是一种统一的请求处理管道,它同时支持本机代码和托管代码模块.实现 IHttp

asp.net应用程序生命周期

HTTP 模块ASP.NET 应用程序生命周期可通过 IHttpModule 类进行扩展.ASP.NET 包含若干实现 IHttpModule 的类,如 SessionStateModule 类.您还可以自行创建实现 IHttpModule 的类. 原文

Asp.Net的应用程序生命周期概述

参考文献: MSDN:Asp.Net应用程序生命周期 博客:选择HttpHandler还是HttpModule?

ASP.NET应用程序生命周期和ASPX页面生命周期图解

ASP.NET应用程序生命周期和ASPX页面生命周期图解,布布扣,bubuko.com

ASP.NET请求管道、应用程序生命周期、整体运行机制

我们知道在ASP.NET中,若要对ASP.NET应用程序进行 初始化并使它处理请求,必须执行一些处理步骤,熟悉应用程序生命周期非常重要,这样才能在适当的生命周期阶段编写代码,达到预期的效果.永远不要做只会拖 控件的.NET程序员,Never!那么你就必须懂ASP.NET应用程序生命周期,懂ASP.NET页面生命周期,懂ASP.NET 服务器控件原理.接下来,我们一起来看看 可以先看一下先导篇 [深入ASP.NET原理系列]--ASP.NET请求管道对Asp.Net WebForm和Asp.Net

ASP.NET应用程序生命周期趣谈(三) HttpModule

在之前的文章中,我们提到过P_Module(HttpModule)这个能干的程序员哥们儿,它通过在项目经理HttpApplication那里得到的授权,插手整个应用程序级别的事件处理.所有的HttpModule都要实现IHttpModule接口,那么我们看IHttpModule的定义: namespace System.Web { public interface IHttpModule { void Dispose(); void Init(HttpApplication context);

ASP.NET应用程序生命周期趣谈(一)

这几天一直在看ASP.NET应用程序生命周期,真是太难了,我理解起来费了劲了,但偏偏它又是那么重要,所以我希望能给大家带来一篇容易理解又好用的文章来帮助学习ASP.NET应用程序生命周期.这篇就是了. 当你访问博客园想看我的这篇文章的时候,这个请求就被博客园的WEB SERVER(IIS)接收到了.博客园IIS看了一眼我的请求,“噢,是.aspx啊,给ASP.NET去处理吧,就把我这个请求给了ASP.NET,并且说:“这个你来处理,你处理完了之后把HTML给我,我好给邱爽一个回复”. ASP.N