最近收到几个疑问: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文档:
在处理该请求时将由 HttpApplication 类执行以下事件。 希望扩展 HttpApplication 类的开发人员尤其需要注意这些事件。 1. 对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。 有关更多信息,请参见 ValidateRequest 和脚本侵入概述。 2. 如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射。 3. 引发 BeginRequest 事件。 4. 引发 AuthenticateRequest 事件。 5. 引发 PostAuthenticateRequest 事件。 6. 引发 AuthorizeRequest 事件。 7. 引发 PostAuthorizeRequest 事件。 8. 引发 ResolveRequestCache 事件。 9. 引发 PostResolveRequestCache 事件。 10. 根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。 如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。 11. 引发 PostMapRequestHandler 事件。 12. 引发 AcquireRequestState 事件。 13. 引发 PostAcquireRequestState 事件。 14. 引发 PreRequestHandlerExecute 事件。 15. 为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 IHttpAsyncHandler.BeginProcessRequest)。 例如,如果该请求针对某页,则当前的页实例将处理该请求。 16. 引发 PostRequestHandlerExecute 事件。 17. 引发 ReleaseRequestState 事件。 18. 引发 PostReleaseRequestState 事件。 19. 如果定义了 Filter 属性,则执行响应筛选。 20. 引发 UpdateRequestCache 事件。 21. 引发 PostUpdateRequestCache 事件。 22. 引发 EndRequest 事件。 23. 引发 PreSendRequestHeaders 事件。 24. 引发 PreSendRequestContent 事件。
图片中还反映了ASP.NET的三种主要的参与者:
1. HttpModule;2. HttpHandlerFactory;3. HttpHandler
有没有有想过:这三种参与者中,每种有多少个参与对象呢?
为了清楚地回答这个问题,准备了下面的表格:
为什么要引入HttpHandlerFactory呢? 请看 细说 HttpHandler 的映射过程,今天就不重复这块内容了。
除开HttpHandlerFactory,们可以发现:在ASP.NET管线中,HttpHandler应该只有一个,而HttpModule是可选的。
进而,们是不是可以这样理解:HttpHandler才是处理请求的主角(不可缺少),HttpModule是配角(可以没有)?