欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET MVC5简介(五)管道处理模型IHttpModule

程序员文章站 2023-04-05 14:55:02
https://www.cnblogs.com/JimmyZhang/archive/2007/09/04/880967.html IHttpModule HTTPRuntime(运行时)。在一个控制台程序中,程序的入口是Program中的Main方法。那么,一个网站的入口在哪里呢?在最开始的ash ......

https://www.cnblogs.com/jimmyzhang/archive/2007/09/04/880967.html

ihttpmodule

httpruntime(运行时)。在一个控制台程序中,程序的入口是program中的main方法。那么,一个网站的入口在哪里呢?在最开始的ashx中,有个processrequest方法,后来在webform中,在后台是一个不分类,继承自page类,在page_load方法中去写代码。其实page类型也有一个processrequest的虚方法。.NET MVC5简介(五)管道处理模型IHttpModule

 

 

 都是这个processrequest方法来处理请求的。在mvc中也是如此。在mvc中,任何一个http请求,一定有一个ihttphandler来处理,在这个接口中,定义了一个processrequest方法。httpapplication继承自ihttphandler接口。任何一个http请求就是一个httpapplication对象来处理的,然后处理过程固定包含权限认证、缓存处理、session处理、cookie出库、生成html、输出客户端,与此同时,千千万万的开发者,又有各种各样的扩展诉求,任何一个环节都有可能扩展,如果是我们来设计,该怎么设计?

其实在mvc框架里面,用到的是观察者模式:

在httpapplication类型,有这些事件:

 //
        // 摘要:
        //     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;

.NET MVC5简介(五)管道处理模型IHttpModule

 

 

 .NET MVC5简介(五)管道处理模型IHttpModule

 

 

 .NET MVC5简介(五)管道处理模型IHttpModule

 

 

 .NET MVC5简介(五)管道处理模型IHttpModule

 

 .NET MVC5简介(五)管道处理模型IHttpModule

 

 .NET MVC5简介(五)管道处理模型IHttpModule

 

 

 这里用的是观察者模式,把固定的步骤直接卸载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了,还有多个事件里面的动作
     }

对httpapplication里面的事件进行动作注册,就叫ihttpmodule。

自定义一个httpmodule+配置文件注册,然后任何一个请求都会执行init里面注册给application事件的动作。

.NET MVC5简介(五)管道处理模型IHttpModule

 

 

 

 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
     }
 }

访问下页面,就是这样的结果:

.NET MVC5简介(五)管道处理模型IHttpModule

 

 

 正常流程下,会按照顺序执行19个事件。

学完httpmodule,我们可以做点什么有用的扩展?

  任何一个请求都会执行httpmoduleinit里面注册给application的事件

  1、日志-性能监控

  2、权限

  3、缓存

  4、页面加点东西

  5、请求过滤

  6、mvc就是一个module的扩展

不适合的:不是针对全部请求的,就不太适合用module,因为有性能损耗

  1、多语言,根据cookie信息去查询不同的数据做不同的展示,如果是全部一套处理,最后httpmodule拦截+处理,适合httpmodule

  2、跳转到不同界面,也不合适

  3、防盗链,针对一类的后缀来处理的,而不是全部请求---判断----再防盗链

在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里面的事件注册动作。