從請(qǐng)求管道深入剖析HttpModule的實(shí)現(xiàn)機(jī)制圖文介紹
更新時(shí)間:2012年11月13日 09:44:22 作者:
想要了解底層的原理必須對(duì)請(qǐng)求處理過(guò)程和頁(yè)面的生命周期有點(diǎn)了解才方便您入門(mén)學(xué)習(xí)一下內(nèi)容,本文將詳細(xì)介紹
想要了解底層的原理必須對(duì)請(qǐng)求處理過(guò)程和頁(yè)面的生命周期有點(diǎn)了解才方便您入門(mén)學(xué)習(xí)一下內(nèi)容:
關(guān)于請(qǐng)求處理過(guò)程和頁(yè)面的生命周期將會(huì)在接下來(lái)的日子為大家做一個(gè)深入的講解。
HttpModule的實(shí)現(xiàn)機(jī)制如下:
1.請(qǐng)求到達(dá)ISAPIRuntime 的時(shí)候通過(guò)ProcessReqeust(下文統(tǒng)稱(chēng)pr ) 方法創(chuàng)建 HttpWrokRequest 對(duì)象。
2.在執(zhí)行ISAPIRuntime 的pr 方法時(shí)候,方法內(nèi)部的HttpRuntime 的pr 方法根據(jù)HttpWorkRequest 對(duì)象創(chuàng)建了上下文對(duì)象 HttpContext 。
3.在HttpRuntime 的 pr 方法內(nèi)部又通過(guò) HttpApplicationFactory 創(chuàng)建了一個(gè)處理應(yīng)用程序的 HttpApplication 實(shí)例。
注意:HttpApplication的創(chuàng)建是根據(jù)Global.asax文件編譯后的類(lèi)型,再通過(guò)反射的方法創(chuàng)建的實(shí)例,由于創(chuàng)建實(shí)例的過(guò)程非常消耗時(shí)間和資源,這個(gè)則使用了對(duì)象池技術(shù)
4.在創(chuàng)建HttpApplication 實(shí)例的過(guò)程中,內(nèi)部會(huì)調(diào)用InitInternal 方法,在這個(gè)方法里面 調(diào)用了HttpModule 的初始化方法,實(shí)現(xiàn)了事件的注冊(cè)。
注意:在實(shí)現(xiàn)事件的注冊(cè)的過(guò)程中,內(nèi)部會(huì)去配置文件里面找是否有配置HttpModule模塊,如果有則通過(guò)反射注冊(cè),沒(méi)有則繼續(xù)往下走,直到方法跳出。這個(gè)過(guò)程就是微軟的插件機(jī)制的體現(xiàn)。
5.事件注冊(cè)完之后,HttpApplication實(shí)例則開(kāi)始調(diào)用自己的pr 方法開(kāi)始執(zhí)行頁(yè)面的生命周期了。
總結(jié):HttpModule 模塊的事件注冊(cè),就是在HttpApplication 實(shí)例內(nèi)部調(diào)用InitInternal 方法,這個(gè)方法里面 調(diào)用了HttpModule 的初始化方法,實(shí)現(xiàn)了事件的注冊(cè)。
下面的代碼是幫助你理解這個(gè)過(guò)程:
1、首先定義一個(gè)上下文 類(lèi) HttpContext
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 上下文
/// </summary>
public class HttpContext
{
}
}
2.定義兩個(gè)接口分別為: IHttpHandler 、IHttpModule
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個(gè)接口主要是在application調(diào)用pr方法的時(shí)候
/// 實(shí)現(xiàn)調(diào)用具體頁(yè)面或一般處理程序的pr方法的。
/// </summary>
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個(gè)接口主要模擬在Application 的 InitInternal方法內(nèi)部實(shí)現(xiàn)事件的注冊(cè)
/// </summary>
public interface IHttpModule
{
void Init(HttpApplication application);
}
}
3、定義一個(gè)頁(yè)面類(lèi) Page
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 頁(yè)面類(lèi)
/// </summary>
public class Page:IHttpHandler
{
/// <summary>
/// 實(shí)現(xiàn)了IHttpHandler接口
/// </summary>
/// <param name="context">上下文</param>
public void ProcessRequest(HttpContext context)
{
Console.WriteLine("頁(yè)面的生命周期....");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("頁(yè)面的生命周期結(jié)束...");
}
}
}
4.定義一個(gè)應(yīng)用程序類(lèi) Application
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
public class HttpApplication:IHttpHandler
{
//初始化方法
public void InitInternal()
{
//從配置文件中讀取所有的注冊(cè)了HttpModule的程序集,然后通過(guò)反射出實(shí)例,并調(diào)用Init方法?。。?下面的MyHttpModule假設(shè)是通過(guò)反射出來(lái)的
IHttpModule httpModule = new MyHttpModule();
httpModule.Init(this);
BindEvent();
}
//Application 自己的事件響應(yīng)方法
private void BindEvent()
{
BeginRequest += new EventHandler(HttpApplication_BeginRequest);
PostResolveRequestCache += new EventHandler(HttpApplication_PostResolveRequestCache);
EndRequest += new EventHandler(HttpApplication_EndRequest);
}
void HttpApplication_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--EndRequest");
}
void HttpApplication_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--PostResolveRequest");
}
void HttpApplication_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--BeginRequest");
}
//把此方法看成是 http 請(qǐng)求處理的管道
public void ProcessRequest(HttpContext context)
{
//19個(gè)事件,23個(gè)步驟
Console.WriteLine("開(kāi)始請(qǐng)求");
//觸發(fā)第一個(gè)事件
BeginRequest(this, null);
//觸發(fā)第七個(gè)事件
PostResolveRequestCache(this, null);
Console.WriteLine("已經(jīng)獲取緩存");
//第七個(gè)和第八個(gè)事件之間,創(chuàng)建頁(yè)面對(duì)象或一般處理程序
IHttpHandler httpHandler = new Page();
Console.WriteLine("創(chuàng)建頁(yè)面對(duì)象");
//在11 和 12 個(gè)事件之間執(zhí)行pr方法
Console.WriteLine("開(kāi)始執(zhí)行頁(yè)面的生命周期");
httpHandler.ProcessRequest(context);
//最后一個(gè)事件
EndRequest(this, null);
Console.WriteLine("結(jié)束請(qǐng)求");
}
public event EventHandler BeginRequest;
public event EventHandler PostResolveRequestCache;
public event EventHandler EndRequest;
}
}
5.模擬請(qǐng)求管道中的執(zhí)行過(guò)程
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
class Program
{
static void Main(string[] args)
{
//ISAPIRuntime
//假設(shè)根據(jù)請(qǐng)求創(chuàng)建了HttpContext上下文
HttpContext context = new HttpContext();
//假設(shè)從HttpApplicationFactory創(chuàng)建出來(lái)
HttpApplication application = new HttpApplication();
//把所有注冊(cè)在配置文件中的HttpModule加載并執(zhí)行其Init方法
application.InitInternal();
//調(diào)用pr方法開(kāi)始執(zhí)行頁(yè)面的pr方法
application.ProcessRequest(context);
Console.ReadKey();
}
}
}
6.自定義一個(gè)HttpModule
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 自定義的HttpModule模塊
/// </summary>
public class MyHttpModule : IHttpModule
{
/// <summary>
/// 實(shí)現(xiàn)了IHttpModule接口
/// </summary>
/// <param name="application"></param>
public void Init(HttpApplication application)
{
//注冊(cè)事件
application.BeginRequest += new EventHandler(application_BeginRequest);
application.PostResolveRequestCache += new EventHandler(application_PostResolveRequestCache);
application.EndRequest += new EventHandler(application_EndRequest);
}
void application_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了EndRequest方法");
}
void application_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了PostResolveRequestCache方法");
}
void application_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了BeginRequest方法");
}
}
}
通過(guò)以上的步驟就實(shí)現(xiàn)了整個(gè)管道的執(zhí)行過(guò)程和HttpModule的實(shí)現(xiàn)原理了。
下面是效果圖:
關(guān)于請(qǐng)求處理過(guò)程和頁(yè)面的生命周期將會(huì)在接下來(lái)的日子為大家做一個(gè)深入的講解。
HttpModule的實(shí)現(xiàn)機(jī)制如下:
1.請(qǐng)求到達(dá)ISAPIRuntime 的時(shí)候通過(guò)ProcessReqeust(下文統(tǒng)稱(chēng)pr ) 方法創(chuàng)建 HttpWrokRequest 對(duì)象。
2.在執(zhí)行ISAPIRuntime 的pr 方法時(shí)候,方法內(nèi)部的HttpRuntime 的pr 方法根據(jù)HttpWorkRequest 對(duì)象創(chuàng)建了上下文對(duì)象 HttpContext 。
3.在HttpRuntime 的 pr 方法內(nèi)部又通過(guò) HttpApplicationFactory 創(chuàng)建了一個(gè)處理應(yīng)用程序的 HttpApplication 實(shí)例。
注意:HttpApplication的創(chuàng)建是根據(jù)Global.asax文件編譯后的類(lèi)型,再通過(guò)反射的方法創(chuàng)建的實(shí)例,由于創(chuàng)建實(shí)例的過(guò)程非常消耗時(shí)間和資源,這個(gè)則使用了對(duì)象池技術(shù)
4.在創(chuàng)建HttpApplication 實(shí)例的過(guò)程中,內(nèi)部會(huì)調(diào)用InitInternal 方法,在這個(gè)方法里面 調(diào)用了HttpModule 的初始化方法,實(shí)現(xiàn)了事件的注冊(cè)。
注意:在實(shí)現(xiàn)事件的注冊(cè)的過(guò)程中,內(nèi)部會(huì)去配置文件里面找是否有配置HttpModule模塊,如果有則通過(guò)反射注冊(cè),沒(méi)有則繼續(xù)往下走,直到方法跳出。這個(gè)過(guò)程就是微軟的插件機(jī)制的體現(xiàn)。
5.事件注冊(cè)完之后,HttpApplication實(shí)例則開(kāi)始調(diào)用自己的pr 方法開(kāi)始執(zhí)行頁(yè)面的生命周期了。
總結(jié):HttpModule 模塊的事件注冊(cè),就是在HttpApplication 實(shí)例內(nèi)部調(diào)用InitInternal 方法,這個(gè)方法里面 調(diào)用了HttpModule 的初始化方法,實(shí)現(xiàn)了事件的注冊(cè)。
下面的代碼是幫助你理解這個(gè)過(guò)程:
1、首先定義一個(gè)上下文 類(lèi) HttpContext
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 上下文
/// </summary>
public class HttpContext
{
}
}
2.定義兩個(gè)接口分別為: IHttpHandler 、IHttpModule
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個(gè)接口主要是在application調(diào)用pr方法的時(shí)候
/// 實(shí)現(xiàn)調(diào)用具體頁(yè)面或一般處理程序的pr方法的。
/// </summary>
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
}
}
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個(gè)接口主要模擬在Application 的 InitInternal方法內(nèi)部實(shí)現(xiàn)事件的注冊(cè)
/// </summary>
public interface IHttpModule
{
void Init(HttpApplication application);
}
}
3、定義一個(gè)頁(yè)面類(lèi) Page
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 頁(yè)面類(lèi)
/// </summary>
public class Page:IHttpHandler
{
/// <summary>
/// 實(shí)現(xiàn)了IHttpHandler接口
/// </summary>
/// <param name="context">上下文</param>
public void ProcessRequest(HttpContext context)
{
Console.WriteLine("頁(yè)面的生命周期....");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("頁(yè)面的生命周期結(jié)束...");
}
}
}
4.定義一個(gè)應(yīng)用程序類(lèi) Application
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
public class HttpApplication:IHttpHandler
{
//初始化方法
public void InitInternal()
{
//從配置文件中讀取所有的注冊(cè)了HttpModule的程序集,然后通過(guò)反射出實(shí)例,并調(diào)用Init方法?。。?下面的MyHttpModule假設(shè)是通過(guò)反射出來(lái)的
IHttpModule httpModule = new MyHttpModule();
httpModule.Init(this);
BindEvent();
}
//Application 自己的事件響應(yīng)方法
private void BindEvent()
{
BeginRequest += new EventHandler(HttpApplication_BeginRequest);
PostResolveRequestCache += new EventHandler(HttpApplication_PostResolveRequestCache);
EndRequest += new EventHandler(HttpApplication_EndRequest);
}
void HttpApplication_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--EndRequest");
}
void HttpApplication_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--PostResolveRequest");
}
void HttpApplication_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應(yīng)方法執(zhí)行了--BeginRequest");
}
//把此方法看成是 http 請(qǐng)求處理的管道
public void ProcessRequest(HttpContext context)
{
//19個(gè)事件,23個(gè)步驟
Console.WriteLine("開(kāi)始請(qǐng)求");
//觸發(fā)第一個(gè)事件
BeginRequest(this, null);
//觸發(fā)第七個(gè)事件
PostResolveRequestCache(this, null);
Console.WriteLine("已經(jīng)獲取緩存");
//第七個(gè)和第八個(gè)事件之間,創(chuàng)建頁(yè)面對(duì)象或一般處理程序
IHttpHandler httpHandler = new Page();
Console.WriteLine("創(chuàng)建頁(yè)面對(duì)象");
//在11 和 12 個(gè)事件之間執(zhí)行pr方法
Console.WriteLine("開(kāi)始執(zhí)行頁(yè)面的生命周期");
httpHandler.ProcessRequest(context);
//最后一個(gè)事件
EndRequest(this, null);
Console.WriteLine("結(jié)束請(qǐng)求");
}
public event EventHandler BeginRequest;
public event EventHandler PostResolveRequestCache;
public event EventHandler EndRequest;
}
}
5.模擬請(qǐng)求管道中的執(zhí)行過(guò)程
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
class Program
{
static void Main(string[] args)
{
//ISAPIRuntime
//假設(shè)根據(jù)請(qǐng)求創(chuàng)建了HttpContext上下文
HttpContext context = new HttpContext();
//假設(shè)從HttpApplicationFactory創(chuàng)建出來(lái)
HttpApplication application = new HttpApplication();
//把所有注冊(cè)在配置文件中的HttpModule加載并執(zhí)行其Init方法
application.InitInternal();
//調(diào)用pr方法開(kāi)始執(zhí)行頁(yè)面的pr方法
application.ProcessRequest(context);
Console.ReadKey();
}
}
}
6.自定義一個(gè)HttpModule
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 自定義的HttpModule模塊
/// </summary>
public class MyHttpModule : IHttpModule
{
/// <summary>
/// 實(shí)現(xiàn)了IHttpModule接口
/// </summary>
/// <param name="application"></param>
public void Init(HttpApplication application)
{
//注冊(cè)事件
application.BeginRequest += new EventHandler(application_BeginRequest);
application.PostResolveRequestCache += new EventHandler(application_PostResolveRequestCache);
application.EndRequest += new EventHandler(application_EndRequest);
}
void application_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了EndRequest方法");
}
void application_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了PostResolveRequestCache方法");
}
void application_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊(cè)了BeginRequest方法");
}
}
}
通過(guò)以上的步驟就實(shí)現(xiàn)了整個(gè)管道的執(zhí)行過(guò)程和HttpModule的實(shí)現(xiàn)原理了。
下面是效果圖:
相關(guān)文章
.net中string類(lèi)型可以作為lock的鎖對(duì)象嗎
lock 關(guān)鍵字是用于在多線程編程中實(shí)現(xiàn)同步和互斥訪問(wèn)的關(guān)鍵字,它的作用是確保共享資源在任意時(shí)刻只能被一個(gè)線程訪問(wèn),從而避免出現(xiàn)競(jìng)態(tài)條件(race condition)和數(shù)據(jù)不一致的問(wèn)題,這篇文章主要介紹了string類(lèi)型可以作為lock的鎖對(duì)象嗎,需要的朋友可以參考下2023-06-06ASP.NET 根據(jù)漢字獲取漢字拼音的首字母(含多音字)
本文分享了一個(gè)函數(shù),這個(gè)函數(shù)可以根據(jù)漢字的字符串獲取其拼音的首字母,以便我們?cè)趯?shí)際開(kāi)發(fā)中使用。2016-04-04.Net Core中使用Quartz.Net實(shí)踐記錄
Quartz.NET是一套很好的任務(wù)調(diào)度框架。下面這篇文章主要給大家介紹了關(guān)于.Net Core中使用Quartz.Net的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09asp.net下中文驗(yàn)證碼,免費(fèi)開(kāi)源代碼
asp.net下中文驗(yàn)證碼,免費(fèi)開(kāi)源代碼...2007-04-04ASP.NET配合jQuery解決跨域調(diào)用的問(wèn)題
這篇文章主要介紹了ASP.NET配合jQuery解決跨域調(diào)用的問(wèn)題,簡(jiǎn)單實(shí)用,需要的朋友可以參考下。2016-06-06ASP.NET?Core中Cookie驗(yàn)證身份用法詳解
本文詳細(xì)講解了ASP.NET?Core中Cookie驗(yàn)證身份的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02ASP.NET Core環(huán)境變量配置和啟動(dòng)設(shè)置講解
這篇文章介紹了ASP.NET Core環(huán)境變量配置和啟動(dòng)設(shè)置的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02ASP.NET Core 文件響應(yīng)壓縮的常見(jiàn)使用誤區(qū)
在微軟官方文檔中,未明確指出文件壓縮功能的使用誤區(qū)。本文將對(duì) ASP.NET Core 文件響應(yīng)壓縮的常見(jiàn)使用誤區(qū)做出說(shuō)明。2021-05-05