.NET MVC5簡介(五)管道處理模型IHttpModule

https://www.cnblogs.com/JimmyZhang/archive/2007/09/04/880967.htmlhtml

IHttpModule緩存

HTTPRuntime(運行時)。在一個控制檯程序中,程序的入口是Program中的Main方法。那麼,一個網站的入口在哪裏呢?在最開始的ashx中,有個ProcessRequest方法,後來在WebForm中,在後臺是一個不分類,繼承自Page類,在Page_Load方法中去寫代碼。其實Page類型也有一個ProcessRequest的虛方法。session

 

 

 都是這個ProcessRequest方法來處理請求的。在MVC中也是如此。在MVC中,任何一個Http請求,必定有一個IHttpHandler來處理,在這個接口中,定義了一個ProcessRequest方法。HttpApplication繼承自IHttpHandler接口。任何一個Http請求就是一個HttpApplication對象來處理的,而後處理過程固定包含權限認證、緩存處理、Session處理、Cookie出庫、生成html、輸出客戶端,與此同時,千千萬萬的開發者,又有各類各樣的擴展訴求,任何一個環節都有可能擴展,若是是咱們來設計,該怎麼設計?app

其實在MVC框架裏面,用到的是觀察者模式:框架

在HttpApplication類型,有這些事件:ide

 //
        // 摘要:
        //     Occurs just before ASP.NET sends HTTP headers to the client.
        public event EventHandler PreSendRequestHeaders;
 //
        // 摘要:
        //     Occurs when the handler is selected to respond to the request.
        public event EventHandler MapRequestHandler;
 //
        // 摘要:
        //     Occurs when the application is disposed.
        public event EventHandler Disposed;
 //
        // 摘要:
        //     Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET
        //     responds to a request.
        public event EventHandler BeginRequest;
 //
        // 摘要:
        //     Occurs when a security module has established the identity of the user.
        public event EventHandler AuthenticateRequest;
 //
        // 摘要:
        //     Occurs when a security module has established the identity of the user.
        public event EventHandler PostAuthenticateRequest;
 //
        // 摘要:
        //     Occurs when a security module has verified user authorization.
        public event EventHandler AuthorizeRequest;
 //
        // 摘要:
        //     Occurs when the user for the current request has been authorized.
        public event EventHandler PostAuthorizeRequest;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes an authorization event to let the caching modules
        //     serve requests from the cache, bypassing execution of the event handler (for
        //     example, a page or an XML Web service).
        public event EventHandler ResolveRequestCache;
 //
        // 摘要:
        //     Occurs when ASP.NET bypasses execution of the current event handler and allows
        //     a caching module to serve a request from the cache.
        public event EventHandler PostResolveRequestCache;
 //
        // 摘要:
        //     Occurs just before ASP.NET sends content to the client.
        public event EventHandler PreSendRequestContent;
 //
        // 摘要:
        //     Occurs when ASP.NET has mapped the current request to the appropriate event handler.
        public event EventHandler PostMapRequestHandler;
 //
        // 摘要:
        //     Occurs when ASP.NET has completed processing all the event handlers for the System.Web.HttpApplication.LogRequest
        //     event.
        public event EventHandler PostLogRequest;
 //
        // 摘要:
        //     Occurs when the managed objects that are associated with the request have been
        //     released.
        public event EventHandler RequestCompleted;
 //
        // 摘要:
        //     Occurs when the request state (for example, session state) that is associated
        //     with the current request has been obtained.
        public event EventHandler PostAcquireRequestState;
 //
        // 摘要:
        //     Occurs just before ASP.NET starts executing an event handler (for example, a
        //     page or an XML Web service).
        public event EventHandler PreRequestHandlerExecute;
 //
        // 摘要:
        //     Occurs when the ASP.NET event handler (for example, a page or an XML Web service)
        //     finishes execution.
        public event EventHandler PostRequestHandlerExecute;
 //
        // 摘要:
        //     Occurs after ASP.NET finishes executing all request event handlers. This event
        //     causes state modules to save the current state data.
        public event EventHandler ReleaseRequestState;
 //
        // 摘要:
        //     Occurs when ASP.NET has completed executing all request event handlers and the
        //     request state data has been stored.
        public event EventHandler PostReleaseRequestState;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes executing an event handler in order to let caching
        //     modules store responses that will be used to serve subsequent requests from the
        //     cache.
        public event EventHandler UpdateRequestCache;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes updating caching modules and storing responses that
        //     are used to serve subsequent requests from the cache.
        public event EventHandler PostUpdateRequestCache;
 //
        // 摘要:
        //     Occurs just before ASP.NET performs any logging for the current request.
        public event EventHandler LogRequest;
 //
        // 摘要:
        //     Occurs when ASP.NET acquires the current state (for example, session state) that
        //     is associated with the current request.
        public event EventHandler AcquireRequestState;
 //
        // 摘要:
        //     Occurs as the last event in the HTTP pipeline chain of execution when ASP.NET
        //     responds to a request.
        public event EventHandler EndRequest;
 //
        // 摘要:
        //     Occurs when an unhandled exception is thrown.
        public event EventHandler Error;
View Code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 這裏用的是觀察者模式,把固定的步驟直接寫在handler裏面,在步驟先後分別放一個事件,而後開發者能夠對事件註冊動做,等着請求進來了,而後就能夠按照順訊執行一下。這種設計是否是很完美?可是仍有不完美的地方,就是每一個請求都要執行這些事件,太多管閒事了。在.NET Core中出現了中間件,比這種更加完美。後續再詳細介紹。性能

請見下列代碼網站

 public class HttpProcessDemo
 {
     public class HttpApplicationDemo : IHttpHandler
     {
         public bool IsReusable => true;

         public event Action BeginRequest;
         public event Action EndRequest;
         public event Action PreSomething1Handler;
         public event Action PostSomething1Handler;
         public event Action PreSomething2Handler;
         public event Action PostSomething2Handler;
         public event Action PreSomething3Handler;
         public event Action PostSomething3Handler;
         public event Action PreSomething4Handler;
         public event Action PostSomething4Handler;
         public event Action PreSomething5Handler;
         public event Action PostSomething5Handler;
         public event Action PreSomething6Handler;
         public event Action PostSomething6Handler;
         public void ProcessRequest(HttpContext context)
         {
             this.BeginRequest?.Invoke();

             this.PreSomething1Handler?.Invoke();
             Console.WriteLine("Something 1");
             this.PostSomething1Handler?.Invoke();

             this.PreSomething2Handler?.Invoke();
             Console.WriteLine("Something 2");
             this.PostSomething2Handler?.Invoke();
             this.PreSomething3Handler?.Invoke();
             Console.WriteLine("Something 3");
             this.PostSomething3Handler?.Invoke();
             this.PreSomething4Handler?.Invoke();
             Console.WriteLine("Something 4");
             this.PostSomething4Handler?.Invoke();

             this.PreSomething5Handler?.Invoke();
             Console.WriteLine("Something 5");
             this.PostSomething5Handler?.Invoke();
             this.PreSomething6Handler?.Invoke();
             Console.WriteLine("Something 6");
             this.PostSomething6Handler?.Invoke();

             this.EndRequest?.Invoke();
         }
         //任何請求進來,只能是 123456
         //事件升級後,能夠在程序啓動時,實例化HttpApplicationDemo後,能夠給事件註冊動做,請求再進來時,處理不只是123456了,還有多個事件裏面的動做
     }
View Code

對HttpApplication裏面的事件進行動做註冊,就叫IHttpModule。ui

自定義一個HttpModule+配置文件註冊,而後任何一個請求都會執行Init裏面註冊給Application事件的動做。this

 

 

 

 public class CustomHttpModule : IHttpModule
 {
     public void Dispose()
     {
         Console.WriteLine();
     }

     public event EventHandler CustomHttpModuleHandler;

     /// <summary>
     /// 註冊動做
     /// </summary>
     /// <param name="context"></param>
     public void Init(HttpApplication application)
     {
         application.BeginRequest += (s, e) =>
           {
               this.CustomHttpModuleHandler?.Invoke(application, null);
           };
         //application.EndRequest += (s, e) =>
         //{
         //    HttpContext.Current.Response.Write("CustomHttpModule.EndRequest");
         //};
         #region 爲每個事件,都註冊了一個動做,向客戶端輸出信息
         application.AcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AcquireRequestState        "));
         application.AuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AuthenticateRequest        "));
         application.AuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AuthorizeRequest           "));
         application.BeginRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "BeginRequest               "));
         application.Disposed += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "Disposed                   "));
         application.EndRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "EndRequest                 "));
         application.Error += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "Error                      "));
         application.LogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "LogRequest                 "));
         application.MapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "MapRequestHandler          "));
         application.PostAcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAcquireRequestState    "));
         application.PostAuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthenticateRequest    "));
         application.PostAuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthorizeRequest       "));
         application.PostLogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostLogRequest             "));
         application.PostMapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostMapRequestHandler      "));
         application.PostReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostReleaseRequestState    "));
         application.PostRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostRequestHandlerExecute  "));
         application.PostResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostResolveRequestCache    "));
         application.PostUpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostUpdateRequestCache     "));
         application.PreRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreRequestHandlerExecute   "));
         application.PreSendRequestContent += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestContent      "));
         application.PreSendRequestHeaders += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestHeaders      "));
         application.ReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "ReleaseRequestState        "));
         application.RequestCompleted += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "RequestCompleted           "));
         application.ResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "ResolveRequestCache        "));
         application.UpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "UpdateRequestCache         "));
         #endregion
     }
 }
View Code

訪問下頁面,就是這樣的結果:

 

 

 正常流程下,會按照順序執行19個事件。

學完HttpModule,咱們能夠作點什麼有用的擴展?

  任何一個請求都會執行HttpModuleInit裏面註冊給Application的事件

  一、日誌-性能監控

  二、權限

  三、緩存

  四、頁面加點東西

  五、請求過濾

  六、MVC就是一個Module的擴展

不適合的:不是針對所有請求的,就不太適合用Module,由於有性能損耗

  一、多語言,根據Cookie信息去查詢不一樣的數據作不一樣的展現,若是是所有一套處理,最後HttpModule攔截+處理,適合httpModule

  二、跳轉到不一樣界面,也不合適

  三、防盜鏈,針對一類的後綴來處理的,而不是所有請求---判斷----再防盜鏈

在HttpModule裏面發佈一個CustomHttpModuleHandler,在Global增長一個動做CustomHttpModuleBingle_CustomHttpModuleHandler(配置文件module名稱_module裏面事件名稱),請求響應時,該事件會執行

protected void CustomHttpModuleBingle_CustomHttpModuleHandler(object sender, EventArgs e)
{
    this.logger.Info("this is CustomHttpModuleBingle_CustomHttpModuleHandler");
}

HttpModule是對HttpApplication的事件動做註冊動做,Global是對HttpModule裏面的事件註冊動做。

相關文章
相關標籤/搜索