ASP.NET底層機制 (上) HttpModule

來源:互聯網
上載者:User
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事件。

以上兩句話,可以用來表示:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.