阅读目录

  • 开始
  • 理解ASP.NET管线
  • 理解HttpApplication
  • 理解HttpHandler
  • 理解HttpModule
  • 三大对象的总结
  • 案例演示
  • 如何选择?

最近收到几个疑问:HttpHandler和HttpModule之间有什么差别,我到底该选择哪个?
之所以有这个疑问,是因为在这二类对象中都可以访问Request, Response对象,都能处理请求。

我原以为在博客 用Asp.net写自己的服务框架 中做了那么多的演示应该把它们的使用方法说清楚了, 然而有些人看了我的那些示例,仍然不知道该如何选择它们,为了实现同一个目标,我既用了HttpHandler,也有用HttpModule。 现在看来,我当时设计的那些示例并不是讲清楚HttpHandler和HttpModule之间有什么差别, 而是在演示如何利用HttpHandler和HttpModule设计一个服务框架。

很庆幸那篇博客内容没有走题,今天只好再来写一篇了。

本文约定:
1. HttpHandler泛指所有实现IHttpHandler接口的类型。
2. HttpModule泛指所有实现IHttpModule接口的类型。
因此,本文将不会特别区分这些类型与接口。

回到顶部

理解ASP.NET管线

HttpHandler和HttpModule,它们都与ASP.NET管线有关,所以我想理解这二类对象必须要理解ASP.NET管线的工作方式。

下图反映了ASP.NET管线的处理流程:

这是一张时序图,我们应该从二个角度来理解它:
1. 有哪些调用动作。
2. 有哪些参与者。

每个调用动作,都反映了ASP.NET管线的处理阶段,它们会引发相应的事件(除GetHandler,ProcessRequest之外), HttpModule则会订阅这些事件,参与到管线处理过程。 这些阶段中,有些阶段还引发了二个事件,完整的管线事件可参考MSDN文档: 

图片中还反映了ASP.NET的三种主要的参与者:
1. HttpModule
2. HttpHandlerFactory
3. HttpHandler

有没有有想过:这三种参与者中,每种有多少个参与对象呢?

为了清楚地回答这个问题,我准备了下面的表格:

管线参与者 每次请求中参与者数量
HttpModule >= 0
HttpHandlerFactory 1
HttpHandler 1

为什么要引入HttpHandlerFactory呢? 请看我的博客 细说 HttpHandler 的映射过程,今天就不重复这块内容了。

除开HttpHandlerFactory,我们可以发现:在ASP.NET管线中,HttpHandler应该只有一个,而HttpModule是可选的。
进而,我们是不是可以这样理解:HttpHandler才是处理请求的主角(不可缺少),HttpModule是配角(可以没有)?

回到顶部

理解HttpApplication

前面我们一直在说ASP.NET管线,那么,谁在控制管线过程?
答案是:HttpApplication对象。
1. HttpApplication细分它的处理过程,在不同阶段引发不同的事件,使得HttpModule通过订阅事件的方式加入到请求的处理过程中。
2. 在请求的处理过程中,HttpApplication对象主要扮演着控制处理流程的推进作用。
3. HttpApplication会在固定的阶段获取一个IHttpHandler实例,然后将请求的响应过程交给具体的IHttpHandler来实现。

HttpApplication如何产生,如何工作? 
1. HttpApplication对象会被重用,当HttpRuntime不能从HttpApplicationFactory获取空闲的实例时,才会创建。
2. HttpRuntime会将每个请求交给一个HttpApplication对象来处理。
3. HttpApplication对象在初始化时负责加载全部的HttpModule。
4. 每个HttpApplication对象会控制属于它的管线过程(前面已解释)。

HttpApplication是个非常重要的类型,它的许多功能都属于框架的基础部分,不需要我们调用, 因此,我们平时不会用到它。

我不想让博客走题,下面来看看今天的主角吧。

回到顶部

理解HttpHandler

前面说到HttpRuntime会将请求交给HttpApplication来处理, 此时你有没有想过这样一个问题:为什么HttpApplication不直接处理请求,而是要再交给一个HttpHandler对象来处理呢?

答案是:每个请求的内容可能并不相同,它们存在多样性,因此ASP.NET采用了抽象工厂模式来处理这些请求。 ASP.NET在web.config的架构中,允许我们指定某些请求映射到一个HttpHandlerFactory,例如:

<!--适用于IIS6的配置-->
<system.web><httpHandlers><add path="*.cspx" verb="*" type="MyMVC.AjaxHandlerFactory, MyMVC" validate="true" /><add path="*.aspx" verb="*" type="MyMVC.MvcPageHandlerFactory, MyMVC" validate="true" /><add path="/mvc/*" verb="*" type="MyMVC.MvcPageHandlerFactory, MyMVC" validate="true" /></httpHandlers>
</system.web><!--适用于IIS7的配置(集成模式)-->
<system.webServer><handlers><add name="AjaxHandlerFactory" verb="*" path="*.cspx" type="MyMVC.AjaxHandlerFactory, MyMVC" preCondition="integratedMode" /><add name="MvcPageHandlerFactory" verb="*" path="*.aspx" type="MyMVC.MvcPageHandlerFactory, MyMVC" preCondition="integratedMode" /><add name="MvcPageHandlerFactory2" verb="*" path="/mvc/*" type="MyMVC.MvcPageHandlerFactory, MyMVC" preCondition="integratedMode" /></handlers>
</system.webServer>

当某个请求与一个规则匹配后,ASP.NET会调用匹配的HttpHandlerFactory的GetHandler方法来获取一个HttpHandler实例, 最后由一个HttpHandler实例来处理当前请求

HttpApplication是如何将请求交给HttpHandler实例来处理的呢?
为了理解这个过程,我们要来看一下IHttpHandler接口的定义:

// 这个接口用于同步调用
// 异步版本的接口用法请参考:http://www.cnblogs.com/fish-li/archive/2011/11/20/2256385.htmlpublic interface IHttpHandler
{// 获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。bool IsReusable { get; }// 通过实现 IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。void ProcessRequest(HttpContext context);
}

HttpApplication在将某个请求交给HttpHandler实例来处理时,是通过接口来调用的(ProcessRequest方法)。

与HttpHandler的相关话题:
1. 异步 HttpHandler:细说ASP.NET的各种异步操作。
2. 如何重用HttpHandler:细说 HttpHandler 的映射过程。

HttpHanlder的典型应用 

通常我去这样创建一个ashx文件(HttpHanlder)响应某种特殊的请求。
所以,我们应该这样理解HttpHanlder:一个HttpHanlder用于响应一类特定的请求。

我们经常用到的HttpHanlder有哪些? 

我们通常使用HttpHanlder做什么? 

回到顶部

理解HttpModule

设计HttpHanlder的目的很明确:生成响应结果。
那么,设计HttpModule又是为什么呢?

前面说过,一个HttpHanlder用于处理一类特定的请求,每个aspx, ashx都可以认为是一类请求。 有时候我们发现所有页面可能都需要某些相同的检查功能(如身份检查), 假如只能使用HttpHanlder,那我们就要让所有页面都去调用那些相同的检查功能。 谁愿意做这些重复的事情? 或许有些人会回答,可以自己实现一个基类,把检查功能放在基类中去调用。 然而,这种做法只能解决重复调用问题,它会让代码失去灵活性(扩展性), 试想一下:如果需要再加入新的检查功能,或者用新的检查方法替换原有的检查逻辑时怎么办? 只能是修改基类了吧?

设计HttpModule的目的正是为了提供一个灵活的方法解决这种功能重用问题。 它采用事件(观察者)的设计模式,将某些HttpHanlder都需要的功能抽取出来, 形成不同的观察者类型,这些观察者类型可以编译成类库形式,供多个网站项目共用。 为了让ASP.NET管线更灵活,ASP.NET允许我们在web.config中自由配置需要的HttpModule,例如:

<!--适用于IIS6的配置-->
<system.web><httpModules><add name="SetOutputCacheModule" type="MyMVC.SetOutputCacheModule, MyMVC"/></httpModules>
</system.web><!--适用于IIS7的配置(集成模式)-->
<system.webServer><modules><add name="SetOutputCacheModule" type="MyMVC.SetOutputCacheModule, MyMVC" preCondition="integratedMode" /></modules>
</system.webServer>

配置只是告诉ASP.NET:这些HttpModule需要运行起来。 有没有想过这些HttpModule到底是如何进入管线运行起来的呢? 前面我只是说了HttpModule会订阅这些事件,那么事件又是在哪里订阅的呢? 还是来看一下IHttpModule接口的定义吧:

// 这个接口用于同步调用
// 异步用法请参考:http://www.cnblogs.com/fish-li/archive/2011/11/20/2256385.htmlpublic interface IHttpModule
{//  初始化模块,并使其为处理请求做好准备。void Init(HttpApplication app);void Dispose();
}

注意这个关键的Init方法,它传入一个HttpApplication类型的参数,有了HttpApplication对象,HttpModule就可以订阅HttpApplication的所有事件了。 请看下面的示例代码: 

HttpModule的典型应用 

这个Module用于给一些在配置文件中指出要缓存的请求设置输出缓存,示例代码已在上篇博客 不修改代码就能优化ASP.NET网站性能的一些方法 介绍过了。 其实设置输出缓存的最根本手段还是调用Response.Cache的一些公开方法,修改输出响应头。

我们用HttpModule做什么事情? 

HttpModule能处理哪些请求呢? 

回到顶部

三大对象的总结

前面我分别介绍了HttpApplication,HttpHanlder和HttpModule,这里再把三者的关系重新梳理一遍。

在请求的处理过程中,HttpApplication对象主要扮演着控制管线处理流程的作用,它负责推进整个处理流程, 除了在不同阶段引发不同的事件外(供HttpModule使用),HttpApplication对象还会根据当前请求寻找一个合适的IHttpApplicationFactory实例, 并最终得到一个IHttpHandler的实例用于处理请求。

设计这三种类型的目的在于:
1. HttpApplication控制处理流程,在不同阶段引发不同的事件。
2. 由于请求的多样性,每个请求会由一个HttpHandler对象来处理。
3. 对于一些通用性的功能,尤其是与响应内容无关的,设计成HttpModule是最合适的。

回到顶部

案例演示

Q:我有一些html文件,需要做身份认证检查(判断Session),我该如何实现?

想好了就来看看我的解决方案: 

Q:我需要压缩所有的ASP.NET请求的响应结果,该怎么实现?

想好了就来看看我的解决方案: 

回到顶部

如何选择?

在结束这篇博客之前,再问问各位读者:现在知道何时选择HttpHandler还是HttpModule了吗?

如果还没有看明白,那我就最后告诉你一个识别方法:
1. 如果要响应一类请求,那么就选择HttpHandler。
2. 如果要修改或者检查所有请求(总之就是不生成响应结果),那就选择HttpModule。

最后给各位留下一个题目,下面这些ASP.NET提供的功能,它们是采用了哪个方式实现的?
1. Session
2. 身份认证
3. URL授权检查
3. 通过trace.axd查看跟踪信息
4. OutputCache
5. 禁止下载config文件
6. 禁止查看下载源代码文件

注意:本文的主题是:选择HttpHandler还是HttpModule,所以请不要扯远了。

原文地址:http://www.cnblogs.com/fish-li/archive/2013/01/04/2844908.html

分类: C# Asp.net
本文转自快乐就好博客园博客,原文链接:http://www.cnblogs.com/happyday56/p/3533671.html,如需转载请自行联系原作者

选择HttpHandler还是HttpModule?相关推荐

  1. HttpHandler与HttpModule区别

    ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后,仍经过Pi ...

  2. HttpHandler和HttpModule 心得介绍

    HttpHandler和HttpModule--入门 ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHan ...

  3. asp.net Forums 之HttpHandler和HttpModule

    我们先说说IHttpHandler和IHttpModule这两个接口. 微软的解释为: IHttpHandler: 定义 ASP.NET 为使用自定义 HTTP 处理程序同步处理 HTTP Web 请 ...

  4. HttpHandler与HttpModule的用处与区别

    HttpHandler与HttpModule的用处与区别 问题1:什么是HttpHandler? 问题2:什么是HttpModule? 问题3:什么时候应该使用HttpHandler什么时候使用Htt ...

  5. ASP.NET内部原理(HttpHandler和HttpModule)

    [IT168 技术文档]在以前的ASP时候,当请求一个*.asp页面文件的时候,这个HTTP请求首先会被一个名为 inetinfo.exe进程所截获,这个进程实际上就是www服务.截获之后它会将这个请 ...

  6. 我心中的核心组件~HttpHandler和HttpModule实现图像的缩放与Url的重写

    回到目录 说在前 对于资源列表页来说,我们经常会把图像做成N多种,大图,小图,中图等等,很是麻烦,在数据迁移时,更是一种痛快,而如果你把图像资源部署到nginx上,那么这种图像缩放就变得很容易了,因为 ...

  7. HttpModule与HttpHandler详解

    ASP.NET对请求处理的过程: 当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给 ASPNET_ISAPI.dll, ...

  8. HttpModule与HttpHandler详解(转)

    一 asp.net请求的处理过程 ------------------- HttpModule必须要掌握的东西 HttpHandler 必须要掌握的东西,非常有用 以上两个的实例 ---------- ...

  9. HttpHandler HttpModule入门篇

    ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后,仍经过Pi ...

最新文章

  1. R语言window函数提取时序数据数据子集(subset):使用xts包将dataframe数据转化为时间序列数据(time series)、使用window函数从时间序列对象中提取数据子集
  2. 我以前用过的一个洗牌算法
  3. SDN教育城域网解决方案
  4. [云炬创业管理笔记]第一章测试1
  5. Java内存图以及堆、栈、常量区、静态区、方法区的区别
  6. 数据结构与算法 Big O 备忘录与现实
  7. 利用python安装opencv_OpenCV Python安装教程
  8. SpringMVC接受JSON参数详解及常见错误总结我改
  9. MathType与Origin是怎么兼容的
  10. html pt兼容,FCKEditor,一个HTML可视化编辑器,兼容很好
  11. mysql在windows配置多节点_Windows环境配置MySQL集群
  12. 游戏开发--开源18---Volity|PhiloGL|impactJs|createjs|C...
  13. 私藏几十款程序员必备效率工具:一次性都给你了!
  14. Proteus常用元件对照表(最全)
  15. encountered an improper argument解决方案
  16. 解决ecshop模板兼容jquery问题
  17. 合格前端系列第十弹-揭秘组件库一二事
  18. Delphi Thread 线程2
  19. base64 string类 放不下_千夜空的推荐 | LOFTER(乐乎) - 让兴趣,更有趣
  20. linux命令教程第六期

热门文章

  1. springboot+vue前后端分离实现宿舍管理系统
  2. JDBC与Druid简单介绍及Druid与MyBatis连接数据库
  3. 二进制安装 kubernetes 1.12(三) - 部署 Master 节点组件
  4. 数据结构 第三周第四周学习小结
  5. poj2739(尺取法+质数筛)
  6. python使用正則表達式
  7. apk反编译工具-apktool
  8. Json在线格式化站点
  9. Win10打不开jar程序的解决方法 [转载]
  10. android双击熄屏代码,Android响应双击屏幕事件