1.ASP時代的HTTP請求處理過程
在IIS的應用程式對應中,IIS會將對asp和asa檔案的請求轉交給asp.dll這個ISAPI來處理
Inetinfo.exe進程,即www服務進程
解釋型處理,每次請求都會重新解釋一次,不適用於大流量請求
2.ASP.NET的HTTP請求處理過程
3.在HttpRuntime中請求處理過程
HttpRequest請求:
進入HttpRumtime——通過HttpApplicationFactory,建立HttpApplication執行個體——進入HttpModule——通過HttpHandlerFactory,建立HttpHandler執行個體
*這個HttpApplication執行個體在HttpModule的Init方法中會用到
4.HttpModule工作原理
負責監聽HttpRequest,同時對HttpRequest增添或者過濾掉一部分內容。
HttpModule實現了介面IHttpModule,我們可以自訂實現該介面的類,從而取代HttpModule。
ASP.NET預設的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;
IHttpModule介面分析:public interface IHttpModule
{
// 銷毀不再被HttpModule使用的資源
void Dispose();
//初始化一個Module,為捕獲HttpRequest做準備
void Init(HttpApplication context);
}
編寫自己的HttpModule://注意要在這個類庫中添加System.Web引用
using System;
using System.Web;
namespace ClassLibraryModule
{
public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.Application_BeginRequest);
context.EndRequest += new EventHandler(this.Application_EndRequest);
}
public void Dispose() { }
//自己要處理私事的兩個方法
public void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
HttpResponse response = application.Response;
HttpRequest request = application.Request;
response.Write("來自Application_BeginRequest");
}
public void Application_EndRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
HttpResponse response = application.Response;
HttpRequest request = application.Request;
response.Write("來自Application_EndRequest");
}
}
}
在Web項目中添加這個類庫的引用,同時在Web.config的system.web標籤中添加: <httpModules>
<add name="Test" type="ClassLibraryModule.MyHttpModule,ClassLibraryModule"></add>
</httpModules>
name可以隨意指定,沒有影響。
type有兩個參數,第一個表示具體哪個類,第二個表示是哪個dll
不需要在Web項目添加對類庫的引用,只是複製一份到bin目錄下即可
於是該網站下的每個頁面都會Response.Write兩句話——這適合做廣告,只要替換成javascript即可
5.HttpModule內部事件機制
HttpApplication執行個體有很多事件,BenginRequest和EndRequest分別是HttpModule容器最開始的和最後的事件
注意,EndRequest之後還會觸發PreSendRequestHeaders事件和PreSendRequestContent事件,這不是在HttpModule外的兩個事件,表示HttpModule結束,即將開始向Client發送資料。
HttpModule容器與HttpHandler容器的互動:
HttpModule容器會將HttpRequest傳遞到HttpHandler容器,這個時間點是ResolveRequestCache事件。
HttpModule容器會建立HttpHandler執行個體作為入口——Session從此生效
觸發AcquireRequestState事件以及PreRequestHandlerExecute事件,
HttpModule容器便將對HttpRequest的控制權轉讓給HttpHandler容器。
HttpHandler容器處理HttpRequest——使用自身的ProcessRequest方法,將對其控制權又還給HttpModule容器——之後Session失效
可以同時載入兩個HttpModule,
<httpModules>
<add name="Test1" type="ClassLibraryModule.MyHttpModule1,ClassLibraryModule1"></add>
<add name="Test2" type="ClassLibraryModule.MyHttpModule2,ClassLibraryModule2"></add>
</httpModules>
這時,根據add標籤的先後,依次執行:
Test1.BeginRequest
Test2.BeginRequest
.....
Test1.EndRequest
Test2.EndRequest
利用HttpModule實現當滿足一定條件時終止此次HttpRequest:
在BeginRequest事件中,使用HttpApplication.CompleteRequest()方法
public void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
application.CompleteRequest();
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
}
在BeginRquest中終止,但是仍然會調用EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件——應該說直接跳轉到EndRequest事件,而不會調用這期間的事件
如果有兩個HttpModule,在第一個Module的BeginRequest中終止,僅僅不會調用第二個Module的BeginRequest,但仍然會調用兩個EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。
以上兩句話,可以用來表示: