想要了解底層的原理必須對請求處理過程和頁面的生命周期有點了解才方便您入門學習一下內容:
關於請求處理過程和頁面的生命周期將會在接下來的日子為大家做一個深入的講解。
HttpModule的實現機制如下:
1.請求到達ISAPIRuntime 的時候通過ProcessReqeust(下文統稱pr ) 方法創建 HttpWrokRequest 對象。
2.在執行ISAPIRuntime 的pr 方法時候,方法內部的HttpRuntime 的pr 方法根據HttpWorkRequest 對象創建了上下文對象 HttpContext 。
3.在HttpRuntime 的 pr 方法內部又通過 HttpApplicationFactory 創建了一個處理應用程序的 HttpApplication 實例。
注意:HttpApplication的創建是根據Global.asax文件編譯後的類型,再通過反射的方法創建的實例,由於創建實例的過程非常消耗時間和資源,這個則使用了對象池技術
4.在創建HttpApplication 實例的過程中,內部會調用InitInternal 方法,在這個方法裡面 調用了HttpModule 的初始化方法,實現了事件的注冊。
注意:在實現事件的注冊的過程中,內部會去配置文件裡面找是否有配置HttpModule模塊,如果有則通過反射注冊,沒有則繼續往下走,直到方法跳出。這個過程就是微軟的插件機制的體現。
5.事件注冊完之後,HttpApplication實例則開始調用自己的pr 方法開始執行頁面的生命周期了。
總結:HttpModule 模塊的事件注冊,就是在HttpApplication 實例內部調用InitInternal 方法,這個方法裡面 調用了HttpModule 的初始化方法,實現了事件的注冊。
下面的代碼是幫助你理解這個過程:
1、首先定義一個上下文 類 HttpContext
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 上下文
/// </summary>
public class HttpContext
{
}
}
2.定義兩個接口分別為: IHttpHandler 、IHttpModule
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個接口主要是在application調用pr方法的時候
/// 實現調用具體頁面或一般處理程序的pr方法的。
/// </summary>
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
}
}
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,這個接口主要模擬在Application 的 InitInternal方法內部實現事件的注冊
/// </summary>
public interface IHttpModule
{
void Init(HttpApplication application);
}
}
3、定義一個頁面類 Page
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 頁面類
/// </summary>
public class Page:IHttpHandler
{
/// <summary>
/// 實現了IHttpHandler接口
/// </summary>
/// <param name="context">上下文</param>
public void ProcessRequest(HttpContext context)
{
Console.WriteLine("頁面的生命周期....");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("頁面的生命周期結束...");
}
}
}
4.定義一個應用程序類 Application
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
public class HttpApplication:IHttpHandler
{
//初始化方法
public void InitInternal()
{
//從配置文件中讀取所有的注冊了HttpModule的程序集,然後通過反射出實例,並調用Init方法!!! 下面的MyHttpModule假設是通過反射出來的
IHttpModule httpModule = new MyHttpModule();
httpModule.Init(this);
BindEvent();
}
//Application 自己的事件響應方法
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自己的事件響應方法執行了--EndRequest");
}
void HttpApplication_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應方法執行了--PostResolveRequest");
}
void HttpApplication_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件響應方法執行了--BeginRequest");
}
//把此方法看成是 http 請求處理的管道
public void ProcessRequest(HttpContext context)
{
//19個事件,23個步驟
Console.WriteLine("開始請求");
//觸發第一個事件
BeginRequest(this, null);
//觸發第七個事件
PostResolveRequestCache(this, null);
Console.WriteLine("已經獲取緩存");
//第七個和第八個事件之間,創建頁面對象或一般處理程序
IHttpHandler httpHandler = new Page();
Console.WriteLine("創建頁面對象");
//在11 和 12 個事件之間執行pr方法
Console.WriteLine("開始執行頁面的生命周期");
httpHandler.ProcessRequest(context);
//最後一個事件
EndRequest(this, null);
Console.WriteLine("結束請求");
}
public event EventHandler BeginRequest;
public event EventHandler PostResolveRequestCache;
public event EventHandler EndRequest;
}
}
5.模擬請求管道中的執行過程
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
class Program
{
static void Main(string[] args)
{
//ISAPIRuntime
//假設根據請求創建了HttpContext上下文
HttpContext context = new HttpContext();
//假設從HttpApplicationFactory創建出來
HttpApplication application = new HttpApplication();
//把所有注冊在配置文件中的HttpModule加載並執行其Init方法
application.InitInternal();
//調用pr方法開始執行頁面的pr方法
application.ProcessRequest(context);
Console.ReadKey();
}
}
}
6.自定義一個HttpModule
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 自定義的HttpModule模塊
/// </summary>
public class MyHttpModule : IHttpModule
{
/// <summary>
/// 實現了IHttpModule接口
/// </summary>
/// <param name="application"></param>
public void Init(HttpApplication application)
{
//注冊事件
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注冊了EndRequest方法");
}
void application_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊了PostResolveRequestCache方法");
}
void application_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注冊了BeginRequest方法");
}
}
}
通過以上的步驟就實現了整個管道的執行過程和HttpModule的實現原理了。
下面是效果圖: