HttpModule
当请求在管道中传递时,HttpApplicaion对象中一系列的事件被触发.我们已经看到这些事件在Global.asax中作为事件被发布.这种方法是特定于应用程序的,可能并不总是你想要的.如果你要建立一个通用的可用被插入任何Web应用程序的HttpApplication事件钩子,你可用使用HttpModule,这是可复用的,不需要特定语应用程序代码的,只需要web.config中的一个条目.
模块本质上是过滤器(fliter)-功能上类似于ISAPI过滤器,但是它工作在ASP.NET请求级别上.模块允许为每个通过HttpApplication对象的请求挂接事件.这些模块作为外部程序集中的类存贮.,在web.config文件中被配置,在应用程序启动时被载入.通过实现特定的接口和方法,模块被挂接到HttpApplication事件链上.多个HttpModule可用被挂接在相同的事件上,事件处理的顺序取决于它们在Web.config中声明的顺序.下面是在Web.config中处理器定义.
type="HttpHandlers.BasicAuth,WebStore"/>
注意你需要指定完整的类型名和不带dll扩展名的程序集名.
模块允许你查看每个收到的Web请求并基于被触发的事件执行一个动作.模块在修改请求和响应数据方面做的非常优秀,可用为特定的程序提供自定义认证或者为发生在ASP.NET中的每个请求增加其他预处理/后处理功能.许多ASP.NET的功能,像认证和会话(Session)引擎都是作为HttpModule来实现的.
虽然HttpModule看上去很像ISAPI过滤器,它们都检查每个通过ASP.NET应用的请求,但是它们只检查映射到单个特定的ASP.NET应用或虚拟目录的请求,也就是只能检查映射到ASP.NET的请求.这样你可以检查所有ASPX页面或者其他任何映射到ASP.NET的扩展名.你不能检查标准的.HTM或者图片文件,除非你显式的映射这些扩展名到ASP.NET ISAPI dll上,就像图1中展示的那样.一个常见的此类应用可能是使用模块来过滤特定目录中的JPG图像内容并在最上层通过GDI+来绘制’样品’字样.
实现一个HTTP模块是非常简单的:你必须实现之包含两个函数(Init()和Dispose())的IHttpModule接口.传进来的事件参数中包含指向HTTPApplication对象的引用,这给了你访问HttpContext对象的能力.在这些方法上你可以挂接到HttpApplication事件上.例如,如果你想挂接AuthenticateRequest事件到一个模块上,你只需像列表5中展示的那样做
列表5:基础的HTTP模块是非常容易实现的
|
记住你的模块访问了HttpContext对象,从这里可以访问到其他ASP.NET管道中固有的对象,如请求(Request)和响应(Response),这样你还可以接收用户输入的信息等等.但是记住有些东西可能是不能访问的,它们只有在处理链的后段才能被访问.
你可以在Init()方法中挂接多个事件,这样你可以在一个模块中实现多个不同的功能.然而,将不同的逻辑分到单独的类中可能会更清楚的将模块进行模块化(译注:这里的模块化和前面的模块没有什么关系)在很多情况下你实现的功能可能需要你挂接多个事件-例如一个日志过滤器可能在BeginRequest事件中记录请求开始时间,然后在EndRequest事件中将请求结束写入到日志中.
注意一个HttoModule和HttpApplication事件中的重点:Response.End()或HttpApplication.CompleteRequest()会在HttpApplication和Module的事件链中”抄近道”.看”注意Response.End()”来获得更多信息.
注意Response.End()
当创建HttpModule或者在Global.asax中实现事件钩子的时候,当你调用Response.End或 Appplication.CompleteRequest的时候要特别注意.这两个函数都结束当前请求并停止触发在HTTP管道中后续的事件,然后发生将控制返回到Web服务器中.当你在处理链的后面有诸如记录日志或对内容进行操作的行为时,因为他们没有被触发,有可能使你上当.例如,sample中logging的例子就会失败,因为如果调用Response.End()的话,EndRequest事件并不会被触发.
HttpHandlers
模块是相当底层的,而且对每个来到ASP.NET应用程序的请求都会被触发.Http处理器更加的专注并处理映射到这个处理器上的请求.
Http处理器需要实现的东西非常简单,但是通过访问HttpContext对象它可以变得非常强大.Http处理器通过实现一个非常简单的IHttpHandler接口(或是它的异步版本,IHttpAsyncHandler),这个接口甚至只含有一个方法-ProcessRequest()-和一个属性IsReusable.关键部分是ProcessRequest(),这个函数获取一个HttpContext对象的实例作为参数.这个函数负责从头到尾处理Web请求.
单独的,简单的函数?太简单了,对吧?好的,简单的接口,但并不弱小!记住WebForm和WebService都是作为Http处理器实现的,所以在这个看上去简单的接口中包装了很强大的能力.关键是这样一个事实,当一个请求来到Http处理器时,所有的ASP.NET的内部对象都被准备和设置好来处理请求了.主要的是HttpContext对象,提供所有相关的请求功能来接收输入并输出回Web服务器.
对一个HTTP处理其来说所有的动作都在这个单独的ProcessRequest()函数的调用中发生.这像下面所展示的这样简单:
publicvoid ProcessRequest(HttpContext context)
{
context.Response.Write("Hello World");
}
也可以像一个可以从HTML模板渲染出复杂表单的WebForm页面引擎那么完整,复杂.通过这个简单,但是强大的接口要做什么,完全取决于你的决定.
因为Context对象对你是可用的,你可用访问Request,Response,Session和Cache对象,所以你拥有所有ASP.NET请求的关键特性,可以获得用户提交的内容并返回你产生的内容给客户端.记住HttpContext对象-它是你在整个ASP.NET请求的生命周期中的”朋友”.
处理器的关键操作应该是将输出写入Response对象或者更具体一点,是Response对象的OutputStream.这个输出是实际上被送回到客户端的.在幕后,ISAPIWorkerRequest管理着将输出流返回到ISAPI ecb的过程.WriteClient方法是实际产生IIS输出的方法.
图7-ASP.NET请求管道通过一系列事件接口来转发请求,提供了更大的灵活性.Application当请求到来并通过管道时作为一个载入Web应用并触发事件的宿主容器.每个请求都沿着配置的Http过滤器和模块的路径走(译注:原文为Http Filters And Modules,应该是指Http Module和Http Handler).过滤器可以检查每个通过管道的请求,Handler允许实现应用程序逻辑或者像Web Form和WebService这样的应用层接口.为了向应用提供输入输出,Context对象在这个处理过程中提供了特定于请求的的信息.
WebForm使用一系列在框架中非常高层的接口来实现一个Http处理器,但是实际上WebForm的Render()方法简单的以使用一个HtmlTextWriter对象将它的最终结果输出到context.Response.OutputStream告终.所以非常梦幻的,终究即使是向WebForm这样高级的工具也只是在Request和Response对象之上进行了抽象而已.
到了这里你可能会疑惑在Http handler中你到底需要处理什么.既然WebForm提供了简单可用的Http Handler实现,那么为什么需要考虑更底层的东西而放弃这扩展性呢?
WebForm对于产生复杂的HTML页面来说是非常强大的,业务层逻辑需要图形布局工具和基于模块的页面.但是WebForm引擎做了一系列overhead intensive的任务.如果你想要做的是从系统中读入一个文件并通过代码将其返回的话,不通过WebForm框架直接返回文件会更有效率.如果你要做的是类似从数据库中读出图片的工作,并不需要使用页面框架-你不需要模板而且确定不需要Web页面并从中捕捉用户事件.
没有理由需要建立一个页面对象和Session并捕捉页面级别的事件-所有这些需要执行对你的任务没有帮助的额外的代码.
所以自定义处理器更加有效率.处理器也可用来做WebForm做不到的事情,例如不需要在硬盘上有物理文件就可用处理请求的能力,也被称为虚拟Url.要做到这个,确认你在图1中展示的应用扩展对话框中关掉了”检查文件存在”选项.
这对于内容提供商来说非常常见,象动态图片处理,XML服务,URL重定向服务提供了vanity Urls,下载管理以及其他,这些都不需要WebForm引擎.
异步HTTP Handler
在这篇文章中我大部分都在讨论同步处理,但是ASP.NET运行时也可以通过异步HTTP handler来支持异步操作.这些处理器自动的将处理”卸载”到独立的线程池的线程中并释放主ASP.NET线程,使ASP.NET线程可以处理其他的请求.不幸的是在1.x版的.NET中,”卸载”后的处理还是在同一个线程池中,所以这个特性之增加了一点点的性能.为了创建真正的异步行为,你必须创建你自己的线程并在回调处理中自己管理他们.
当前版本的ASP.NET 2.0 Beta 2在IhttpHandlerAsync(译注:此处应该是指IHttpAsyncHandler,疑为作者笔误)接口和Page类两方面做了一些对异步处理的改进,提供了更好的性能,但是在最终发布版本中这些是否会保留.
我说的这些对你来说够底层了吗?
唷-我们已经走完了整个请求处理过程了.这过程中有很多底层的信息,我对HTTP模块和HTTP处理器是怎么工作的并没有描述的非常详细.挖掘这些信息相当的费时间,我希望在了解了ASP.NET底层机制后,你能获得和我一样的满足感.
在结束之前让我们快速的回顾一下我在本文中讨论的从IIS到处理器(handler)的过程中,事件发生的顺序
·IIS获得请求
·检查脚本映射中,此请求是否映射到aspnet_isapi.dll
·启动工作进程 (IIS5中为aspnet_wp.exe,IIS6中为w3wp.exe)
·.NET运行时被载入
·IsapiRuntime.ProcessRequest()被非托管代码调用
·为每个请求创建一个IsapiWorkerRequest
·HttpRuntime.ProcessRequest()被工作进程调用
·以IsapiWorkerRequest对象为参数创建HttpContext对象
·调用HttpApplication.GetApplicationInstance()来从池中取得一个对象实例
·调用HttpApplication.Init()来开始管道事件并挂接模块和处理器
·HttpApplicaton.ProcessRequest被调用以开始处理.
·管道中的事件被依次触发
·处理器被调,ProcessRequest函数被触发
·控制返回到管道中,后处理事件被依次触发
有了这个简单的列表,记住这些东西并把他们拼在一起就变得容易多了.我时常看看它来加深记忆.所以现在,回去工作,做一些不那么抽象的事情…
虽然我都是基于ASP.NET1.1来进行讨论的,不过在ASP.NET2.0中这些处理过程看上去并没有发生太大的变化.
| 共5页: 上一页 [1] [2] [3] [4] 5 | ||
|
| 关于 Spring.net ASP.NET 的 |
|
||||
| · 技术人求职简历完备手册 · 华为员工自杀频频拷问.. · 视频访谈:网管员如何踏.. · 首届中国IT工程师生态.. · 思科全球CEO钱伯斯第七.. · 北漂技术人90天求职纪实 · 2007年互联网大会 · 龙芯要做中国的“奔腾” |
· IPv6协议--拓展网络无.. · 国际文档格式标准开战 · 微软出价446亿美元收购.. · 贝恩资本携手华为22亿.. · Linux——从菜鸟到高手 · SOA 面向服务架构 · 2008年4月全国计算机等.. · 微软Forefront企业安全.. |
|||
|
||||
| · SQL Server 2008/2005.. · SOA 面向服务架构 · SQL Server 2008/2005.. · iSCSI应用与发展 · RAID——磁盘阵列基础 · 中间件应用技术专题 · SQL Server入门到精通 · 病毒查杀专题 |
· 国际文档格式标准开战 · 路由器设置与口令恢复 · Linux防火墙 · 打造安全服务器 · SOA 面向服务架构 · PHP开发应用手册 · ADSL应用面面俱到 · 入侵防护系统(IPS)初探 |
|||
|
||||
| · iSCSI应用与发展 · 中间件应用技术专题 · SQL Server入门到精通 · SQL Server 2008/2005.. · SOA 面向服务架构 · iSCSI应用与发展 · RAID——磁盘阵列基础 · 病毒查杀专题 |
· 路由器设置与口令恢复 · SOA 面向服务架构 · 了解统一威胁管理(UTM).. · ADSL应用面面俱到 · ADSL应用面面俱到 · PHP开发应用手册 · 中间件应用技术专题 · Linux防火墙 |
|||