HttpHandler与HttpModule

来源:互联网 发布:淘宝直播代购是正品吗 编辑:程序博客网 时间:2024/05/16 18:29

ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后,仍经过Pipeline中各个HttpModule的处理,最后将HTML发送到客户端浏览 器中。

HttpModule会在页面处理前和后对页面进行处理,所以它不会影响真正的页面请求。通常用在给每个页面的头部或者尾部添加一些信息(如版 权声明)等.

 

IHttpModule与IHttpHandler的区别整理
1.先后次序.先IHttpModule,后IHttpHandler. 注:Module要看你响应了哪个事件,一些事件是在Handler之前运行的,一些是在Handler之后运行的
2.对请求的处理上:
   IHttpModule是属于大小通吃类型,无论客户端请求的是什么文件,都会调用到它;例如aspx,rar,html的请求.
   IHttpHandler则属于挑食类型,只有ASP.net注册过的文件类型(例如aspx,asmx等等)才会轮到调用它.
3.IHttpHandler按照你的请求 生成响应的内容,IHttpModule对请求进行预处理,如验证、修改、过滤等等,同时也可以对响应进行处理

4.“HttpHandler是处理请求的主要对象”,但HttpModule却可以随意指定将某个请求交给某个处理器来执行!

甚至,HttpModule也可以直接处理请求,完全不给HttpHandler工作的机会!

 

HttpModule

 继承System.Web.IHttpModule接口,实现自己的HttpModule类。必须要实现接口的两个方法:Init和Dispose。在 Init中,可以添加需要截取的事件;Dispose用于资源的释放,如果在Init中创建了自己的资源对象,请在Dispose中进行释放。

例: 

[csharp] view plaincopy
  1. <span style="font-family:'Microsoft YaHei';">   public class TestHttpModule:IHttpModule  
  2.     {  
  3.         public void Dispose()  
  4.         { }  
  5.         public void Init(HttpApplication context)  
  6.         {  
  7.             context.BeginRequest += new EventHandler(context_BeginRequest);  
  8.         }  
  9.         void context_BeginRequest(object sender, EventArgs e)  
  10.         {  
  11.             HttpApplication appliction = sender as HttpApplication;  
  12.             appliction.Response.Write("HttpModule请求的URL:" + appliction.Request.Url.AbsolutePath);  
  13.         }  
  14.     }</span>  


自定义HttpModule的用途,有全局的身份/权限验证、自定义网站访问/操作日志的记录、处于管理/调试等目的对站点进行监控追踪 等

 

HttpHandler是完全的对Http Request的截取。
    首先,继承System.Web.IHttpHandler接口,实现自己的HttpHandler类。必须要实现接口的ProcessRequest方 法和IsReusable属性。ProcessRequest方法中完成对每个Http Request的处理,发送处理结果的HTML到输出缓存中。IsReusable属性被.Net Framework调用,用以确定这个HttpHandler的实例是否可以被重用于同类型其它的Request处理。
    如果你在自己的HttpHandler类中,需要读取或者是写Session值,需要再继承一个接口IRequiresSessionState。这个接 口没有任何方法,只是一个标记接口。继承这个接口之后,就可以在自己的HttpHandler中访问Session,可以在Session中写入值。
例:    

[csharp] view plaincopy
  1. <span style="font-family:'Microsoft YaHei';">public class TestHandler:IHttpHandler  
  2.     {  
  3.         public bool IsReusable  
  4.         { get { return true; } }  
  5.         public void ProcessRequest(HttpContext context)  
  6.         {  
  7.             string s = context.Request.Url.AbsolutePath;  
  8.             context.Server.Execute("default.aspx?execute=" + context.Server.UrlEncode(s));//URL重定向  
  9.         }  
  10.     }  
  11. <add verb="*" path="*.shtml" type="UI.Core.Http.TestHandler,UI"/></span>  

对于请求时的 a.shtml可以不存在


IHttpModule与IHttpHandler的区别主要有两点(实际上大家看MSDN时应该也注意到了):
    1.先后次序.先IHttpModule,后IHttpHandler.
    2.对请求的处理上:
        IHttpModule是属于大小通吃类型,无论客户端请求的是什么文件,都会调用到它;例如aspx,rar,html的请求.
        IHttpHandler则属于挑食类型,只有ASP.net注册过的文件类型(例如aspx,asmx等等)才会轮到调用它.


HttpModule

   HttpModule的加载方式:前面我说过“Asp.net会为每个请求分配一个HttpApplication对象”,在每个HttpApplication对象的初始化操作中, 它会加载所有在web.config中注册的HttpModule。 在 ASP.NET 内部,HttpRuntime 管理一个定义在 System.Web 命名空间下的 HttpApplicationFactory 类的实例,HttpApplicationFactory 通过工厂模式管理 HttpApplication 对象,在 HttpApplicationFactory 内部维护了一个 HttpApplication 对象池,使得被创建的 HttpApplication 对象可以被重复使用。每一个 HttpApplication 对象每一次仅仅用于处理一个请求,因此在多次请求中每个HttpModule的Init事件是有可能被多次调用的。 许多人喜欢在这里做各类初始化的操作,那么请注意在这里修改静态变量成员时的线程安全问题。 特别地,如果要执行程序初始化的操作,那么还是把代码放在Global.asax的Application_Start中去处理吧, HttpModule的Init事件并不合适。

   为HttpModule选择订阅合适的管线事件:这是非常重要的,订阅不同的事件,产生的结果也会不一样。 原因也很简单,在Asp.net运行环境中,并不只有一个HttpModule,某个HttpModule的判断可能要依据其它HttpModule的输出结果, 而且在某些(晚期的)管线事件中,也不能再修改输出数据。 在后面的示例中,DirectProcessRequestMoudle订阅了PostAuthorizeRequest事件,如果订阅BeginRequest事件或许将得到更好的性能, 但是,在BeginRequest事件中,身份认证模块还没有工作,因此每个请求在这个事件阶段都属于“未登录”状态。

    

httpmodule看不见的性能问题

前面我介绍了HttpModule的重要优点:高重用性。只要写好一个HttpModule可以放在任何Asp.net项目中使用,非常方便。

不过,再好的东西也不能滥用。HttpModule也可以对性能产生负面影响。 原因也很简单:对于每个Asp.net请求,每个HttpModule都会在它们所订阅的事件中, 去执行一些操作逻辑。这些操作逻辑或许对一些请求是无意义的,但仍会执行。 因此,计算机将会白白浪费一些资源去执行一些无意义的代码。

知道了原因,解决办法也就很清楚了:
1. 去掉不需要的HttpModule
2. 在每个HttpModule的事件处理器中,首先要确定是不是自己所需要处理的请求。对一些不相关的请求,应该立即退出。

在我们创建一个Asp.net项目时,如果不做任何修改,微软已经为我们加载了好多HttpModule 。请看以下代码:

<span style="font-family: 'Microsoft YaHei';"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">protected void </span>Page_Load(<span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">object </span>sender, <span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(43, 145, 175);">EventArgs </span>e){    <span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(43, 145, 175);">HttpApplication </span>app <span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">= </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(43, 145, 175);">HttpContext</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>Current<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>ApplicationInstance;            <span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(43, 145, 175);">StringBuilder </span>sb <span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">= </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">new </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(43, 145, 175);">StringBuilder</span>();    <span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">foreach</span>( <span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">string </span>module <span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">in </span>app<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>Modules<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>AllKeys )         sb<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>AppendFormat(module)<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>Append(<span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(163, 21, 21);">"<br />"</span>);    Response<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>Write(sb<span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">.</span>ToString());}</span>

输出结果如下:

总共有14个。
哎,大多数是我肯定不会用到的,但它们却被加载了,因此,在它们所订阅的事件中,它们的代码将会检查所有的请求, 那些无意义的代码将有机会执行。如果您不想视而不见,那么请在web.config中做类似的修改,将不需要的Module移除。

<span style="font-family: 'Microsoft YaHei';"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;"><</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(163, 21, 21);">httpModules</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">>    <</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(163, 21, 21);">remove </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">name</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">=</span>"<span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">Session</span>"<span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">/>    <</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(163, 21, 21);">remove </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: red;">name</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">=</span>"<span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">RoleManager</span>"<span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">/></</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(163, 21, 21);">httpModules</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: blue;">></span></span>

0 0
原创粉丝点击