httpappplication 和 httpmodule 的理解(轉(zhuǎn)載,寫的很好)
2017-06-28 15:53 mi-戰(zhàn)斧 閱讀(655) 評(píng)論(0) 收藏 舉報(bào)第一部分:轉(zhuǎn)載自Artech IIS與ASP.NET管道
ASP.NET管道
以IIS 6.0為例,在工作進(jìn)程w3wp.exe中,利用Aspnet_ispai.dll加載.NET運(yùn)行時(shí)(如果.NET運(yùn)行時(shí)尚未加載)。IIS 6引入了應(yīng)用程序池的概念,一個(gè)工作進(jìn)程對(duì)應(yīng)著一個(gè)應(yīng)用程序池。一個(gè)應(yīng)用程序池可以承載一個(gè)或者多個(gè)Web應(yīng)用,每個(gè)Web應(yīng)用映射到一個(gè)IIS虛擬目錄。與IIS 5.x一樣,每一個(gè)Web應(yīng)用運(yùn)行在各自的應(yīng)用程序域中。
如果HTTP.SYS接收到的HTTP請(qǐng)求是對(duì)該Web應(yīng)用的第一次訪問,當(dāng)成功加載了運(yùn)行時(shí)后,會(huì)通過AppDomainFactory為該Web應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序域(AppDomain)。隨后,一個(gè)特殊的運(yùn)行時(shí)IsapiRuntime被加載。IsapiRuntime定義在程序集System.Web中,對(duì)應(yīng)的命名空間為System.Web.Hosting。IsapiRuntime會(huì)接管該HTTP請(qǐng)求。
IsapiRuntime會(huì)首先創(chuàng)建一個(gè)IsapiWorkerRequest對(duì)象,用于封裝當(dāng)前的HTTP請(qǐng)求,并將該IsapiWorkerRequest對(duì)象傳遞給ASP.net運(yùn)行時(shí):HttpRuntime,從此時(shí)起,HTTP請(qǐng)求正式進(jìn)入了ASP.Net管道。根據(jù)IsapiWorkerRequest對(duì)象,HttpRuntime會(huì)創(chuàng)建用于表示當(dāng)前HTTP請(qǐng)求的上下文(Context)對(duì)象:HttpContext。
隨著HttpContext被成功創(chuàng)建,HttpRuntime會(huì)利用HttpApplicationFactory創(chuàng)建新的或者獲取現(xiàn)有的HttpApplication對(duì)象。實(shí)際上,ASP.NET維護(hù)著一個(gè)HttpApplication對(duì)象池,HttpApplicationFactory從池中選取可用的HttpApplication用戶處理HTTP請(qǐng)求,處理完畢后將其釋放到對(duì)象池中。HttpApplicationFactory負(fù)責(zé)處理當(dāng)前的HTTP請(qǐng)求。
在HttpApplication初始化過程中,會(huì)根據(jù)配置文件加載并初始化相應(yīng)的HttpModule對(duì)象。對(duì)于HttpApplication來說,在它處理HTTP請(qǐng)求的不同的階段會(huì)觸發(fā)不同的事件(Event),而HttpModule的意義在于通過注冊(cè)HttpApplication的相應(yīng)的事件,將所需的操作注入整個(gè)HTTP請(qǐng)求的處理流程。ASP.NET的很多功能,比如身份驗(yàn)證、授權(quán)、緩存等,都是通過相應(yīng)的HttpModule實(shí)現(xiàn)的。
而最終完成對(duì)HTTP請(qǐng)求的處理實(shí)現(xiàn)在另一個(gè)重要的對(duì)象中:HttpHandler。對(duì)于不同的資源類型,具有不同的HttpHandler。比如.aspx頁對(duì)應(yīng)的HttpHandler為System.Web.UI.Page,WCF的.svc文件對(duì)應(yīng)的HttpHandler為System.ServiceModel.Activation.HttpHandler。上面整個(gè)處理流程如圖7所示。
圖7 ASP.NET 處理管道
HttpApplication
HttpApplication是整個(gè)ASP.NET基礎(chǔ)架構(gòu)的核心,它負(fù)責(zé)處理分發(fā)給它的HTTP請(qǐng)求。由于一個(gè)HttpApplication對(duì)象在某個(gè)時(shí)刻只能處理一個(gè)請(qǐng)求,只有完成對(duì)某個(gè)請(qǐng)求的處理后,HttpApplication才能用于后續(xù)的請(qǐng)求的處理。所以,ASP.NET采用對(duì)象池的機(jī)制來創(chuàng)建或者獲取HttpApplication對(duì)象。具體來講,當(dāng)?shù)谝粋€(gè)請(qǐng)求抵達(dá)的時(shí)候,ASP.NET會(huì)一次創(chuàng)建多個(gè)HttpApplication對(duì)象,并將其置于池中,選擇其中一個(gè)對(duì)象來處理該請(qǐng)求。當(dāng)處理完畢,HttpApplication不會(huì)被回收,而是釋放到池中。對(duì)于后續(xù)的請(qǐng)求,空閑的HttpApplication對(duì)象會(huì)從池中取出,如果池中所有的HttpApplication對(duì)象都處于繁忙的狀態(tài),ASP.NET會(huì)創(chuàng)建新的HttpApplication對(duì)象。
HttpApplication處理請(qǐng)求的整個(gè)生命周期是一個(gè)相對(duì)復(fù)雜的過程,在該過程的不同階段會(huì)觸發(fā)相應(yīng)的事件。我們可以注冊(cè)相應(yīng)的事件,將我們的處理邏輯注入到HttpApplication處理請(qǐng)求的某個(gè)階段。我們接下來介紹的HttpModule就是通過HttpApplication事件注冊(cè)的機(jī)制實(shí)現(xiàn)相應(yīng)的功能的。表1按照實(shí)現(xiàn)的先后順利列出了HttpApplication在處理每一個(gè)請(qǐng)求時(shí)觸發(fā)的事件名稱。
表1
|
名稱 |
描述 |
|
BeginRequest |
HTTP管道開始處理請(qǐng)求時(shí),會(huì)觸發(fā)BeginRequest事件 |
|
AuthenticateRequest,PostAuthenticateRequest |
ASP.NET先后觸發(fā)這兩個(gè)事件,使安全模塊對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證 |
|
AuthorizeRequest,PostAuthorizeRequest |
ASP.NET先后觸發(fā)這兩個(gè)事件,使安全模塊對(duì)請(qǐng)求進(jìn)程授權(quán) |
|
ResolveRequestCache,PostResolveRequestCache |
ASP.NET先后觸發(fā)這兩個(gè)事件,以使緩存模塊利用緩存的直接對(duì)請(qǐng)求直接進(jìn)程響應(yīng)(緩存模塊可以將響應(yīng)內(nèi)容進(jìn)程緩存,對(duì)于后續(xù)的請(qǐng)求,直接將緩存的內(nèi)容返回,從而提高響應(yīng)能力)。 |
|
PostMapRequestHandler |
對(duì)于訪問不同的資源類型,ASP.NET具有不同的HttpHandler對(duì)其進(jìn)程處理。對(duì)于每個(gè)請(qǐng)求,ASP.NET會(huì)通過擴(kuò)展名選擇匹配相應(yīng)的HttpHandler類型,成功匹配后,該實(shí)現(xiàn)被觸發(fā) |
|
AcquireRequestState,PostAcquireRequestState |
ASP.NET先后觸發(fā)這兩個(gè)事件,使?fàn)顟B(tài)管理模塊獲取基于當(dāng)前請(qǐng)求相應(yīng)的狀態(tài),比如SessionState |
|
PreRequestHandlerExecute,PostRequestHandlerExecute |
ASP.NET最終通過一請(qǐng)求資源類型相對(duì)應(yīng)的HttpHandler實(shí)現(xiàn)對(duì)請(qǐng)求的處理,在實(shí)行HttpHandler前后,這兩個(gè)實(shí)現(xiàn)被先后觸發(fā) |
|
ReleaseRequestState,PostReleaseRequestState |
ASP.NET先后觸發(fā)這兩個(gè)事件,使?fàn)顟B(tài)管理模塊釋放基于當(dāng)前請(qǐng)求相應(yīng)的狀態(tài) |
|
UpdateRequestCache,PostUpdateRequestCache |
ASP.NET先后觸發(fā)這兩個(gè)事件,以使緩存模塊將HttpHandler處理請(qǐng)求得到的相應(yīng)保存到輸出緩存中 |
|
LogRequest,PostLogRequest |
ASP.NET先后觸發(fā)這兩個(gè)事件為當(dāng)前請(qǐng)求進(jìn)程日志記錄 |
|
EndRequest |
整個(gè)請(qǐng)求處理完成后,EndRequest事件被觸發(fā) |
對(duì)于一個(gè)ASP.NET應(yīng)用來說,HttpApplication派生于global.asax文件,我們可以通過創(chuàng)建global.asax文件對(duì)HttpApplication的請(qǐng)求處理行為進(jìn)行定制。global.asax采用一種很直接的方式實(shí)現(xiàn)了這樣的功能,這種方式既不是我們常用的方法重寫(Method Overriding)或者事件注冊(cè),而是直接采用方法名匹配。在global.asax中,我們按照這樣的方法命名規(guī)則進(jìn)行事件注冊(cè):Application_{Event Name}。比如Application_BeginRequest方法用于處理HttpApplication的BeginRequest事件。如果通過VS創(chuàng)建一個(gè)global.asax文件,下面是默認(rèn)的定義。
1: <%@ Application Language="C#" %>
2: <script runat="server">
3: void Application_Start(object sender, EventArgs e) {}
4: void Application_End(object sender, EventArgs e) {}
5: void Application_Error(object sender, EventArgs e) {}
6: void Session_Start(object sender, EventArgs e) {}
7: void Session_End(object sender, EventArgs e) {}
8: </script>
HttpModule
ASP.NET為創(chuàng)建各種.NET Web應(yīng)用提供了強(qiáng)大的平臺(tái),它擁有一個(gè)具有高度可擴(kuò)展性的引擎,并且能夠處理對(duì)于不同資源類型的請(qǐng)求。那么,是什么成就了ASP.NET的高可擴(kuò)展性呢? HttpModule功不可沒。
從功能上講,HttpModule之于ASP.NET,就好比ISAPI Filter之于IIS一樣。IIS將接收到的請(qǐng)求分發(fā)給相應(yīng)的ISAPI Extension之前,注冊(cè)的ISAPI Filter會(huì)先截獲該請(qǐng)求。ISAPI Filter可以獲取甚至修改請(qǐng)求的內(nèi)容,完成一些額外的功能。與之相似地,當(dāng)請(qǐng)求轉(zhuǎn)入ASP.NET管道后,最終負(fù)責(zé)處理該請(qǐng)求的是與請(qǐng)求資源類型相匹配的HttpHandler對(duì)象,但是在Handler正式工作之前,ASP.NET會(huì)先加載并初始化所有配置的HttpModule對(duì)象。HttpModule在初始化的過程中,會(huì)將一些功能注冊(cè)到HttpApplication相應(yīng)的事件中,那么在HttpApplication整個(gè)請(qǐng)求處理生命周期中的某個(gè)階段,相應(yīng)的事件會(huì)被觸發(fā),通過HttpModule注冊(cè)的事件處理程序也得以執(zhí)行。
所有的HttpModule都實(shí)現(xiàn)了IHttpModule接口,下面是IHttpModule的定義。其中Init方法用于實(shí)現(xiàn)HttpModule自身的初始化,該方法接受一個(gè)HttpApplication對(duì)象,有了這個(gè)對(duì)象,事件注冊(cè)就很容易了。
1: public interface IHttpModule
2: {
3: void Dispose();
4: void Init(HttpApplication context);
5: }
ASP.NET提供的很多基礎(chǔ)構(gòu)件(Infrastructure)功能都是通過相應(yīng)的HttpModule實(shí)現(xiàn)的,下面類列出了一些典型的HttpModule:
- OutputCacheModule:實(shí)現(xiàn)了輸出緩存(Output Caching)的功能;
- SessionStateModule:在無狀態(tài)的HTTP協(xié)議上實(shí)現(xiàn)了基于會(huì)話(Session)的狀態(tài);
- WindowsAuthenticationModule + FormsAuthenticationModule + PassportAuthentication- Module:實(shí)現(xiàn)了3種典型的身份認(rèn)證方式:Windows認(rèn)證、Forms認(rèn)證和Passport認(rèn)證;
- UrlAuthorizationModule + FileAuthorizationModule:實(shí)現(xiàn)了基于Uri和文件ACL(Access Control List)的授權(quán)。
而另外一個(gè)重要的HttpModule與WCF相關(guān),那么就是System.ServiceModel. Activation.HttpModule。HttpModule定義在System.ServiceModel程序集中,在默認(rèn)的情況下,HttpModule完成了基于IIS的寄宿工作。
除了這些系統(tǒng)定義的HttpModule之外,我們還可以自定義HttpMoudle。通過Web.config,我們可以很容易地將其注冊(cè)到我們的Web應(yīng)用中。
HttpHandler
如果說HttpModule相當(dāng)于IIS的ISAPI Filter的話,我們可以說HttpHandler則相當(dāng)于IIS的ISAPI Extension,HttpHandler在ASP.NET中扮演請(qǐng)求的最終處理者的角色。對(duì)于不同資源類型的請(qǐng)求,ASP.NET會(huì)加載不同的Handler來處理,也就是說.aspx page與.asmx web service對(duì)應(yīng)的Handler是不同的。
所有的HttpHandler都實(shí)現(xiàn)了接口IHttpHandler。下面是IHttpHandler的定義,方法ProcessRequest提供了處理請(qǐng)求的實(shí)現(xiàn)。
1: public interface IHttpHandler
2: {
3: void ProcessRequest(HttpContext context);
4: bool IsReusable { get; }
5: }
對(duì)于某些HttpHandler,具有一個(gè)與之相關(guān)的HttpHandlerFactory,用于創(chuàng)建或者獲取相應(yīng)的HttpHandler。HttpHandlerFactory實(shí)現(xiàn)接口IHttpHandlerFactory,方法GetHandler用于創(chuàng)建新的HttpHandler,或者獲取已經(jīng)存在的HttpHandler。
1: public interface IHttpHandlerFactory
2: {
3: IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
4: void ReleaseHandler(IHttpHandler handler);
5: }
HttpHandler和HttpHandlerFactory的類型都可以通過相同的方式配置到Web.config中。下面一段配置包含對(duì)3種典型的資源類型的HttpHandler配置:.aspx,.asmx和.svc。可以看到基于WCF Service的HttpHandler類型為:System.ServiceModel.Activation.HttpHandler。
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.web>
4: <httpHandlers>
5: <add path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/>
6: <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True"/>
7: <add path="*.asmx" verb="*" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="False"/>
8: </httpHandlers>
9: </system.web>
10: </configuration>
第二部分:轉(zhuǎn)自 HttpModule的認(rèn)識(shí)
HttpModule是向?qū)崿F(xiàn)類提供模塊初始化和處置事件。當(dāng)一個(gè)HTTP請(qǐng)求到達(dá)HttpModule時(shí),整個(gè)ASP.NET Framework系統(tǒng)還并沒有對(duì)這個(gè)HTTP請(qǐng)求做任何處理,也就是說此時(shí)對(duì)于HTTP請(qǐng)求來講,HttpModule是一個(gè)HTTP請(qǐng)求的“必經(jīng)之路”,所以可以在這個(gè)HTTP請(qǐng)求傳遞到真正的請(qǐng)求處理中心(HttpHandler)之前附加一些需要的信息在這個(gè)HTTP請(qǐng)求信息之上,或者針對(duì)截獲的這個(gè)HTTP請(qǐng)求信息作一些額外的工作,或者在某些情況下干脆終止?jié)M足一些條件的HTTP請(qǐng)求,從而可以起到一個(gè)Filter過濾器的作用。
1、asp.net的HTTP請(qǐng)求處理過程
說明:
(1)、客戶端瀏覽器向服務(wù)器發(fā)出一個(gè)http請(qǐng)求,此請(qǐng)求會(huì)被inetinfo.exe進(jìn)程截獲,然后轉(zhuǎn)交給aspnet_isapi.dll進(jìn)程,接著它又通過Http Pipeline的管道,傳送給aspnet_wp.exe這個(gè)進(jìn)程,接下來就到了.net framework的HttpRunTime處理中心,處理完畢后就發(fā)送給用戶瀏覽器。
(2)、當(dāng)一個(gè)http請(qǐng)求被送入到HttpRuntime之后,這個(gè)Http請(qǐng)求會(huì)繼續(xù)被送入到一個(gè)被稱之為HttpApplication Factory的一個(gè)容器當(dāng)中,而這個(gè)容器會(huì)給出一個(gè)HttpApplication實(shí)例來處理傳遞進(jìn)來的http請(qǐng)求,而后這個(gè)Http請(qǐng)求會(huì)依次進(jìn)入到如下幾個(gè)容器中:HttpModule --> HttpHandler Factory --> HttpHandler。當(dāng)系統(tǒng)內(nèi)部的HttpHandler的ProcessRequest方法處理完畢之后,整個(gè)Http Request就被處理完成了,客戶端也就得到相應(yīng)的東東了。
(3)完整的http請(qǐng)求在asp.net framework中的處理流程:
HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->Http Pipeline-->ASPNET_WP.EXE-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
也就是說一個(gè)HTTP請(qǐng)求在HttpModule容器的傳遞過程中,會(huì)在某一時(shí)刻(ResolveRequestCache事件)將這個(gè)HTTP請(qǐng)求傳遞給HttpHandler容器。在這個(gè)事件之后,HttpModule容器會(huì)建立一個(gè)HttpHandler的入口實(shí)例,但是此時(shí)并沒有將HTTP請(qǐng)求控制權(quán)交出,而是繼續(xù)觸發(fā)AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之后,HttpModule窗口就會(huì)將控制權(quán)暫時(shí)交給HttpHandler容器,以便進(jìn)行真正的HTTP請(qǐng)求處理工作。
而在HttpHandler容器內(nèi)部會(huì)執(zhí)行ProcessRequest方法來處理HTTP請(qǐng)求。在容器HttpHandler處理完畢整個(gè)HTTP請(qǐng)求之后,會(huì)將控制權(quán)交還給HttpModule,HttpModule則會(huì)繼續(xù)對(duì)處理完畢的HTTP請(qǐng)求信息流進(jìn)行層層的轉(zhuǎn)交動(dòng)作,直到返回到客戶端為止。
PS:紅色的HttpApplication實(shí)例在HttpModule的Init方法中會(huì)用到。
(4)如果想在中途截獲一個(gè)httpRequest并做些自己的處理,就應(yīng)該在HttpRuntime運(yùn)行時(shí)內(nèi)部來做到這一點(diǎn),確切的說是在HttpModule這個(gè)容器中來實(shí)現(xiàn)。
2、HttpModule工作原理
負(fù)責(zé)監(jiān)聽HttpRequest,同時(shí)對(duì)HttpRequest增添或者過濾掉一部分內(nèi)容。也就是說,當(dāng)一個(gè)HTTP請(qǐng)求到達(dá)HttpModule時(shí),整個(gè)ASP.NET Framework系統(tǒng)還并沒有對(duì)這個(gè)HTTP請(qǐng)求做任何處理,也就是說此時(shí)對(duì)于HTTP請(qǐng)求來講,HttpModule是一個(gè)HTTP請(qǐng)求的“必經(jīng)之路”,所以可以在這個(gè)HTTP請(qǐng)求傳遞到真正的請(qǐng)求處理中心(HttpHandler)之前附加一些需要的信息在這個(gè)HTTP請(qǐng)求信息之上,或者針對(duì)截獲的這個(gè)HTTP請(qǐng)求信息作一些額外的工作,或者在某些情況下干脆終止?jié)M足一些條件的HTTP請(qǐng)求,從而可以起到一個(gè)Filter過濾器的作用。
HttpModule實(shí)現(xiàn)了接口IHttpModule,我們可以自定義實(shí)現(xiàn)該接口的類,從而取代HttpModule。
asp.net默認(rèn)的HttpModule如下:
System.Web.SessionState.SessionStateModule;
System.Web.Security.WindowsAuthenticationModule;
System.Web.Security.FormsAuthenticationModule;
System.Web.Security.PassportAuthenticationModule;
System.Web.Security.UrlAuthorizationModule;
System.Web.Security.FileAuthorizationModule;
3、編寫自己的HttpModule
要實(shí)現(xiàn)HttpModule,必須實(shí)現(xiàn)接口IHttpModule。下面是IHttpModule接口分析:
using System;
namespace System.Web
{
public interface IHttpModule
{
// 銷毀不再被HttpModule使用的資源
void Dispose();
// 初始化一個(gè)Module,為捕獲HttpRequest做準(zhǔn)備
void Init(HttpApplication context);
}
}
下面是自己的HttpModule:
using System;
using System.Web;
namespace ClassLibrary1
{
public class MyHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
context.EndRequest += new EventHandler(Application_EndRequest);
}
public void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
HttpResponse response = context.Response;
response.Write("這是來自自定義HttpModule中有BeginRequest");
}
public void Application_EndRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
HttpResponse response = context.Response;
response.Write("這是來自自定義HttpModule中有EndRequest");
}
}
}
web.config
<httpModules>
<add name="myHttpModule" type="ClassLibrary1.MyHttpModule,ClassLibrary1"/>
</httpModules>
default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("<br/><br/>來自Default.aspx頁面<br/>");
}
}
4、HttpModule內(nèi)部事件機(jī)制和生命周期
HttpModule對(duì)HttpApplication實(shí)例進(jìn)行處理,而HttpApplication有很多事件(對(duì)應(yīng)不同的生命期),這樣就衍生出HttpModule內(nèi)部事件機(jī)制和生命周期。
(1)、HttpModule的事件
| BeginRequest | 指示請(qǐng)求處理開始 |
| AuthenticateRequest | 封裝請(qǐng)求身份驗(yàn)證過程 |
| AuthorizeRequest | 封裝檢查是否能利用以前緩存的輸出頁面處理請(qǐng)求的過程 |
| ResolveRequestCache | 從緩存中得到相應(yīng)時(shí)候觸發(fā) |
| AcquireRequestState | 加載初始化Session時(shí)候觸發(fā) |
| PreRequestHandlerExecute | 在Http請(qǐng)求進(jìn)入HttpHandler之前觸發(fā) |
| PostRequestHandlerExecute | 在Http請(qǐng)求進(jìn)入HttpHandler之后觸發(fā) |
| ReleaseRequestState | 存儲(chǔ)Session狀態(tài)時(shí)候觸發(fā) |
| UpdateRequestCache | 更新緩存信息時(shí)觸發(fā) |
| EndRequest | 在Http請(qǐng)求處理完成的時(shí)候觸發(fā) |
| PreSendRequestHenaders | 在向客戶端發(fā)送Header之前觸發(fā) |
| PreSendRequestConternt | 在向客戶端發(fā)送內(nèi)容之前觸發(fā) |
說明:
a、BenginRequest和EndRequest分別是HttpModule容器最開始的和最后的事件;
b、EndRequest之后還會(huì)觸發(fā)PreSendRequestHeaders事件和PreSendRequestContent事件,這不是在HttpModule外的兩個(gè)事件,表示HttpModule結(jié)束,即將開始向Client發(fā)送數(shù)據(jù)。
(2)、驗(yàn)證HttpModule生命周期
與HttpHandler的交互: ![]()
說明:
a、HttpModule容器會(huì)將HttpRequest傳遞到HttpHandler容器,這個(gè)時(shí)間點(diǎn)是ResolveRequestCache事件
b、HttpModule容器會(huì)建立HttpHandler實(shí)例作為入口——Session從此生效
c、觸發(fā)AcquireRequestState事件以及PreRequestHandlerExecute事件
d、HttpModule容器便將對(duì)HttpRequest的控制權(quán)轉(zhuǎn)讓給HttpHandler容器
e、HttpHandler容器處理HttpRequest——使用自身的ProcessRequest方法,將對(duì)其控制權(quán)又還給HttpModule容器——之后Session失效。
驗(yàn)證生命周期代碼:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace MyHttpModule
{
public class ValidaterHttpModuleEvents : IHttpModule
{
public void Dispose()
{ }
/// <summary>
/// 驗(yàn)證HttpModule事件機(jī)制
/// </summary>
/// <param name="application"></param>
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(application_BeginRequest);
application.EndRequest += new EventHandler(application_EndRequest);
application.AcquireRequestState += new EventHandler(application_AcquireRequestState);
application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest);
application.AuthorizeRequest += new EventHandler(application_AuthorizeRequest);
application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);
application.PostRequestHandlerExecute += new EventHandler(application_PostRequestHandlerExecute);
application.ReleaseRequestState += new EventHandler(application_ReleaseRequestState);
application.ResolveRequestCache += new EventHandler(application_ResolveRequestCache);
application.PreSendRequestHeaders += new EventHandler(application_PreSendRequestHeaders);
application.PreSendRequestContent += new EventHandler(application_PreSendRequestContent);
}
private void application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_BeginRequest<br/>");
}
private void application_EndRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_EndRequest<br/>");
}
private void application_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreRequestHandlerExecute<br/>");
}
private void application_PostRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PostRequestHandlerExecute<br/>");
}
private void application_ReleaseRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_ReleaseRequestState<br/>");
}
private void application_AcquireRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AcquireRequestState<br/>");
}
private void application_PreSendRequestContent(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreSendRequestContent<br/>");
}
private void application_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreSendRequestHeaders<br/>");
}
private void application_ResolveRequestCache(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_ResolveRequestCache<br/>");
}
private void application_AuthorizeRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AuthorizeRequest<br/>");
}
private void application_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AuthenticateRequest<br/>");
}
}
}
<add name="HttpModule1" type="MyHttpModule.HttpModule1,MyHttpModule"/>
<add name="HttpModule2" type="MyHttpModule.HttpModule2,MyHttpModule"/>
HttpModule1和HttpModule2模仿ValidaterHttpModuleEvents編寫(除了類名改變外,事件和方法不變),不貼代碼了。運(yùn)行結(jié)果如下:
從運(yùn)行結(jié)果可以看到,在web.config文件中引入自定義HttpModule的順序就決定了多個(gè)自定義HttpModule在處理一個(gè)HTTP請(qǐng)求的接管順序。
(3)、利用HttpModule實(shí)現(xiàn)終止此次HttpRequest請(qǐng)求
在BeginRequest事件中,使用HttpApplication.CompleteRequest()方法可以實(shí)現(xiàn)當(dāng)滿足一定條件時(shí)終止此次HttpRequest請(qǐng)求
using System;
using System.Web;
namespace ClassLibrary1
{
public class MyHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}
public void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
application.CompleteRequest();
application.Context.Response.Write("請(qǐng)求被終止");
}
}
}
說明:
a、對(duì)于一個(gè)HttpModule,在BeginRquest中終止,但是仍然會(huì)調(diào)用EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。也可以說是直接跳轉(zhuǎn)到EndRequest事件,而不會(huì)調(diào)用這期間的事件
b、如果有兩個(gè)HttpModule,在第一個(gè)HttpModule的BeginRequest中終止,僅僅不會(huì)調(diào)用第二個(gè)HttpModule的BeginRequest,但仍然會(huì)調(diào)用兩個(gè)EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。看下面的圖示:
浙公網(wǎng)安備 33010602011771號(hào)