HttpModule與HttpHandler

HttpModule的工作過程:

HttpModule是向實現類提供模塊初始化和處置事件的,當一個http請求到達httpModule時,整個Asp.Net Framework系統還沒有對這個Http請求做任何處理,也就是說此時對於Http請求來說,httpModule是http請求的必經之路,所以可以在這個http請求傳遞到真正的請求處理中心(HttpHandler)之前附加一些需要的信息在這個http請求信息之上,或者針對截獲的這個http請求做一些額外的工作,或者在某些情況下乾脆終止滿足一些條件的請求,從而起到了一個Filter過濾器的作用

深入瞭解HttpModule

一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件之後,HttpModule容器會建立一個HttpHandler的入口實例,但是此時並沒有將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之後,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。

而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之後,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動作,直到返回到客戶端爲止。

深入瞭解HttpModule

一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件之後,HttpModule容器會建立一個HttpHandler的入口實例,但是此時並沒有將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之後,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。

而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之後,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動作,直到返回到客戶端爲止。

HttpModule與HttpHandler

示例2:驗證HttpModule生命週期

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

namespace MyHttpModule

{

public class ValidaterHttpModule : IHttpModule

{

#region IHttpModule 成員

public void Dispose()

{}

public void Init(HttpApplication application)

{

application.BeginRequest += new EventHandler(application_BeginRequest);

application.EndRequest += new EventHandler(application_EndRequest);

application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);

application.PostRequestHandlerExecute += new EventHandler(application_PostRequestHandlerExecute);

application.ReleaseRequestState += new EventHandler(application_ReleaseRequestState);

application.AcquireRequestState += new EventHandler(application_AcquireRequestState);

application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest);

application.AuthorizeRequest += new EventHandler(application_AuthorizeRequest);

application.ResolveRequestCache += new EventHandler(application_ResolveRequestCache);

application.PreSendRequestHeaders += new EventHandler(application_PreSendRequestHeaders);

application.PreSendRequestContent += new EventHandler(application_PreSendRequestContent);

}

void application_PreSendRequestContent(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_PreSendRequestContent
");

}

void application_PreSendRequestHeaders(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_PreSendRequestHeaders
");

}

void application_ResolveRequestCache(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_ResolveRequestCache
");

}

void application_AuthorizeRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_AuthorizeRequest
");

}

void application_AuthenticateRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_AuthenticateRequest
");

}

void application_AcquireRequestState(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_AcquireRequestState
");

}

void application_ReleaseRequestState(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_ReleaseRequestState
");

}

void application_PostRequestHandlerExecute(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_PostRequestHandlerExecute
");

}

void application_PreRequestHandlerExecute(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_PreRequestHandlerExecute
");

}

void application_EndRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_EndRequest
");

}

void application_BeginRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.Context.Response.Write("application_BeginRequest
");

}

#endregion

}

}

HttpModule與HttpHandler

多個自定義的Http Module的運作

從運行結果可以看到,在web.config文件中引入自定義HttpModule的順序就決定了多個自定義HttpModule在處理一個HTTP請求的接管順序。注:系統默認那幾個HttpModule是最先衩ASP.NET Framework所加載上去的。

如果我們把上面的兩個httpMudel都註冊在web.config中,輸出的結果是

我來自自定義HttpModule中的BeginRequest
application_BeginRequest
application_AuthenticateRequest
application_AuthorizeRequest
application_ResolveRequestCache
application_AcquireRequestState
application_PreRequestHandlerExecute

窗體頂端

窗體底端

application_PostRequestHandlerExecute
application_ReleaseRequestState
我來自自定義HttpModule中的EndRequest
application_EndRequest
application_PreSendRequestHeaders
application_PreSendRequestContent

我們可以發現不同的HttpMudel模塊是並進執行的,相同的方法會在一起執行,

HttpModule中終止此次的HTTP請求

可以利用HttpModule通過調用HttpApplication.CompleteRequest()方法實現當滿足某一個條件時終止此次的HTTP請求。

需要注意的是,即使調用了HttpApplication.CompleteRequest()方法終止了一個HTTP請求,ASP.NET Framework仍然會觸發HttpApplication後面的這3個事件:EndRequest事件、PreSendRequestHeaders事件、PreSendRequestContent事件。

如果存在多個自定義的HttpModule的話,當Module1終止了一個HTTP請求,這個HTTP請求將不會再觸發Module2中相應的事件了,但Module2的最後三個事件仍會被觸發。

void application_BeginRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

application.CompleteRequest();

application.Context.Response.Write("application_BeginRequest
");

}

輸出的結果:

我來自自定義HttpModule中的BeginRequest
application_BeginRequest
我來自自定義HttpModule中的EndRequest
application_EndRequest
application_PreSendRequestHeaders
application_PreSendRequestContent

所以我們可以通過httpMudel對所有的請求進行監聽,對不符合的請求都可以做出相應的處理,從上面的圖中我們也可以看出http請求的執行過程,最終都會交個httpHandler去處理,然後在通過httpMudel返回到客戶端

同HttpHandler對應來看,這些事件,有些在HttpHandler之前發生,有些在HttpHandler處理完後發生。瞭解事件發生的順序非常重要,因爲,服務器端的對象在不同的時間段有着不同的表現。例子之一是Session的使用。不是所有的事件中都能對Session進行處理,而只能在有限的幾個事件中進行處理。詳細的過程可以參考下面的HTTP Request處理生命週期圖。

HttpModule與HttpHandler

上面的這個圖又一次展示了它的用處,在平時的開發中,我們可以使用httpMudel開發權限管理系統,比如後臺,不是每一個人都可以知道url就進入到系統中,要在登錄的時候授權限纔可以,我們這個時候就可以在httpMudel中去處理是否授權,其他的如過濾危險字符串,防止sql注入,在這裏就不在一一介紹了,下面就來看看httpHandler類

概述

HttpHandler是一個HTTP請求的真正處理中心,也正是在這個HttpHandler容器中,ASP.NET Framework才真正地對客戶端請求的服務器頁面做出編譯和執行,並將處理過後的信息附加在HTTP請求信息流中再次返回到HttpModule中。

IHttpHandler如何處理HTTP請求

當一個HTTP請求經同HttpModule容器傳遞到HttpHandler容器中時,ASP.NET Framework會調用HttpHandler的ProcessRequest成員方法來對這個HTTP請求進行真正的處理。以一個ASPX頁面爲例,正是在這裏一個ASPX頁面才被系統處理解析,並將處理完成的結果繼續經由HttpModule傳遞下去,直至到達客戶端。

對於ASPX頁面,ASP.NET Framework在默認情況下是交給System.Web.UI.PageHandlerFactory這個HttpHandlerFactory來處理的。所謂一個HttpHandlerFactory,所謂一個HttpHandlerFactory,是指當一個HTTP請求到達這個HttpHandler Factory時,HttpHandlerFactory會提供出一個HttpHandler容器,交由這個HttpHandler容器來處理這個HTTP請求。

一個HTTP請求都是最終交給一個HttpHandler容器中的ProcessRequest方法來處理的。

HttpModule與HttpHandler

public class MyFirstHandler : IHttpHandler,IRequiresSessionState

{

#region IHttpHandler 成員

public bool IsReusable

{

get { return true; }

}

public void ProcessRequest(HttpContext context)

{

context.Response.Write("

Hello HttpHandler

");

context.Session["Test"] = "測試HttpHandler容器中調用Session";

context.Response.Write(context.Session["Test"]);

}

#endregion

}

}

在Web.config中加入如下配置:

從上面的代碼中可以看出需要實現IsReusable屬性和ProcessRequest方法,其中IsReusable屬性表示是否有好重用該Httphandler,而ProcessRequest測試請求最終的處理方法,該方法需要一個HttpContext實例作爲參數,用於在httpMudel與httphandler之間傳遞參數,也可以用於保持某個完整請求的相應的信息!

在實現很多功能中,我們都可以使用,比如圖片加水印,防止盜鏈等!

發佈了25 篇原創文章 · 獲贊 2 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章