原文地址:http://www.cnblogs.com/skm-blog/p/3188697.html

如果您看了我的前四篇文章,应该知道目前Http请求已经流到了HttpModule这个程序员手中了,而且我们可以注册自己的HttpModule并且可以在里面注册一些事件来控制这个Http请求,但是到目前为止我们还没有真正的处理这个Http请求,那究竟什么时候开始处理呢,又是怎样处理的呢,下面我们来简单探讨一下!

其实是在HttpModule中触发PreRequestHandlerExecute事件之后,才真正把控制权交给了HttpHandler这个程序员,在第一篇中我们说到,HttpHandler它他天生就会处理页面,它用了一招“乾坤大挪移”的功夫,就把上下文Context中的Request对象给处理了(就是处理了Http请求),并且把最终生成的Html填充的Context中的Response对象中,然后就又一步一步传给了IIS,IIS又给了请求者。

那么:

1、   所谓的“乾坤大挪移”到底是个什么功夫呢

2、  P_Handler又是如何被调用如何消亡的呢?

3、  我们自己是否也可以创建HttpHandler呢?

4 、   HttpHandler和我们常用的.ashx又是什么关系呢?

从字面上我们也可以看出,HttpHandler就是handle http(request)的,就像程序员,就是(做)程序的人员一样,所以P_Handler就是个典型的HttpRequest处理人员。我们也知道IHttpHandler接口,它就像是一个认证,任何通过了IHttpHandler认证(实现了这个接口)的人员(handler),都可以处理HttpRequest。这个认证主要有两个内容(方法):1,ProcessRequest;2,IsReusable。

asp.net中有很多默认的HttpHandler,当然每种类型的文件对应了不同的Handler去处理,我们可以从C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config这个路径下找到一个叫做web.config的文件,打开如下:

  <httpHandlers>
<add path="eurl.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" />
<add path="trace.axd" verb="*" type="System.Web.Handlers.TraceHandler" validate="True" />
<add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="True" />
<add verb="*" path="*_AppService.axd" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False" />
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" />
<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" />
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" />
<add path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False" />
<add path="*.rem" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False" />
<add path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False" />
<add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.master" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.skin" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.browser" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.sitemap" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.dll.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="True" />
<add path="*.exe.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="True" />
<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.csproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.vb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.vbproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.webinfo" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.licx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.resx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.resources" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.mdb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.vjsproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.java" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.jsl" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ldb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ad" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.dd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ldd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.sd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.cd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.adprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.lddprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.sdm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.sdmDocument" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.mdf" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ldf" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.exclude" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.refresh" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.rules" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.xamlx" verb="*" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.aspq" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cshtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cshtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" />
<add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="True" />
</httpHandlers>

<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="true" />我们可以知道我们项目中的web.config文件为什么不能访问了,原来是被 HttpForbiddenHandler给屏蔽了,我估计它是直接返回了一个错误,这样我们就不能访问这些资源,同样的,.sitemap, .asax, ..cs, .csproj等等我们熟悉的项目中的文件都是使用HttpForbiddenHandler来屏蔽掉的。

拿<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" />做例子,给大家稍微解释一下:

path就是说所请求的文件的类型 verb代表请求的方式 如Get,Post,*代表全部;type代表由System.Web.UI命名空间下的PageHandlerFactory这个类去处理。Validate=True代表允许的意思。(如有错误,还请留言)

那么我们可以看到,我们最最常访问的页面.aspx原来是交由PagehandlerFactory类处理的,那么PageHandlerFactory又是什么呢,反编译一下可以看到如下:

我们可以看到这个类没有继承IHttpHandler这个接口,那么我们前面不是说所有处理Http请求的类都必须实现IHttpHandler这个接口吗?这是怎么回事呢,接着看,我们发现原理这个PageHandlerFactory类有两个很特别的方法,一个是GetHandler,一个是GetHandlerHelper,反编译看一下,我们发现GetHandler方法内部直接调用GetHandlerHelper方法,就不贴出来了,那么我们看一下GetHandlerHelper内部是什么样的?如下

看到这里我想你是不是很熟悉了啊,它原来返回一个Page类,怪不得我们每次建立一个.aspx页面都会默认继承自Page类呢,再看看Page类的定义如下

public class Page : TemplateControl, IHttpHandler
{
}
我们更加的确信,原来一个.aspx请求过来都是由Page类去处理的啊。也就是说page类就是专门处理.aspx页面请求的一个Httphandler。那么下面我们还有几个问题没有解决:
第一:怎么定义自己的HttpHandler。
第二:HttpHandler中的PR方法到底怎么样执行的,有哪些事件,顺序如何。
听我慢慢道来:
要定义我们自己的HttpHandler其实也很容易
首先:创建一个类,实现IHttpHandler接口,我写的代码如下
namespace ClassLibrary2
{
public class MyHttpHandler:IHttpHandler
{
public bool IsReusable
{
get { throw new NotImplementedException(); }
} public void ProcessRequest(HttpContext context)
{
HttpResponse response = context.Response;
response.Write("这是自定义的HttpHandler");
}
}
}

然后:在web.config文件中配置一下我们的MyHttpHandler是处理哪种类型的文件(本实例一.song格式的文件为例,宋是本人的姓),代码如下:
 <httpHandlers>
<add verb="*" path="*.song" type="ClassLibrary2.MyHttpHandler,ClassLibrary2 " />
</httpHandlers>

最后:在web服务器也就是IIS上配置一下,有些人不明白为什么,其实道理很简单,当我们请求Default.song这个文件时,IIS看到.song就不知道交给谁处理了,所以我们在IIS上配置就是为了告诉IIS还交给aspnet_isapi.dll文件处理,还走正常的.aspx页面请求的管道,不同的是经过HttpModule之后,这个请求不在交给page类处理了,而是转交给了我们自己定义的MyHttpHandler去处理了。配置如下:

本人用的IIS7.0步骤如下:

第一:找到处理程序映射选项,如图

第二:双击处理程序映射,在右侧点击添加脚本映射,如图

第三:还是在右侧点击添加管理处理程序,如图

这样我们在浏览器中请求Default.song(这个文件不存在),IIS看到后缀名是.song的文件就会交给aspnet_isapi.dll文件处理,流过HttpModule之后就会交给我们自己定义的MyHttpHandler处理,结果如下:

看到这里您应该对HttpHandler有一个整体的了解了,但是他内部的PR方法究竟怎么样执行的,执行了哪些事件,顺序又是怎么样的呢,我们还不清楚,这篇文章写的有点长了,怕有些人没有耐性看,所以我打算放到下一篇和大家探讨,请继续关注。

本系列:

一:Asp.Net生命周期系列一

二:Asp.Net生命周期系列二

三:Asp.Net生命周期系列三

四:Asp.Net生命周期系列四

(转)Asp.Net生命周期系列五的更多相关文章

  1. Asp.Net生命周期系列五

    如果您看了我的前四篇文章,应该知道目前Http请求已经流到了HttpModule这个程序员手中了,而且我们可以注册自己的HttpModule并且可以在里面注册一些事件来控制这个Http请求,但是到目前 ...

  2. Asp.Net生命周期系列三

    上文讲到了HttpRunTime主要做了三个事情,我们先回忆一下. 第一:雇佣了项目经理(HttpApplication). 第二:建立了HttpModule列表,项目经理(HttpRunTime)就 ...

  3. Asp.Net生命周期系列四

    上回我们说的当一个Http请求来到HttpModule这里的时候,Asp.Net内部并未对这个Http请求做出任何的处理,我们可以对这个Http请求添加一些我们需要的信息,以方便我们控制这个Http请 ...

  4. (转)Asp.Net生命周期系列三

    原文地址:http://www.cnblogs.com/skm-blog/p/3178862.html 上文讲到了HttpRunTime主要做了三个事情,我们先回忆一下. 第一:雇佣了项目经理(Htt ...

  5. Asp.Net生命周期系列六

    上篇说到当一个Http请求流到HttpHandler这里时才开始对它的处理,那么一个请求经过HttpHandler之后, 到底怎么对它处理呢,也就是说HttpHandler会触发哪些事件,触发的顺序如 ...

  6. Asp.Net生命周期系列二

    在上回书开始的时候我们提到博客园的IIS看了一眼我的请求后就直接交给ASP.NET去处理了,并且要求ASP.NET处理完之后返回HTML以供展示. 那么我们不仅要问: 1,    IIS肯定是没有眼睛 ...

  7. (转)Asp.Net生命周期系列一

    原文地址:http://www.cnblogs.com/skm-blog/archive/2013/07/07/3176713.html Asp.Net生命周期对于初级甚至中级程序员来说,一直都是一个 ...

  8. Asp.Net生命周期系列一

    Asp.Net生命周期对于初级甚至中级程序员来说,一直都是一个难题,很多程序员不了解生命周期,导致使用Asp.Net做开发感觉很不灵活,感觉太多东西被微软封装好了,我们不能改变,其实只要你稍微了解一下 ...

  9. Asp.Net复习篇之Asp.Net生命周期与Asp.Net页的生命周期

    Asp.Net生命周期与Asp.Net页的生命周期是一个比较重要的话题,有时可能似乎知道一些,但又说不出个所以然,而且时常把这两个概念混淆.现在也是该好好理清思路,把这两个概念搞懂. Asp.Net生 ...

随机推荐

  1. [转]javascript中基本类型和引用类型的区别分析

    基本类型和引用类型 ECMAScript包含两个不同类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段:引用类型值指由多个值构成的对象.当我们把变量赋值给一个变量时,解析器首先要做的就是确 ...

  2. ecmall允许上传的图片大小

    $uploader->allowed_type($type); $uploader->allowed_size($size);  ecmall上传类型大小是这样定义,你可以去文件中搜索相关 ...

  3. ALUA and SRM

    A couple important (ALUA and SRM) notes There’s some internal dialog today on our “VMware Champions” ...

  4. 【转】JMeter远程测试

    详解JMeter远程测试(1) 如果运行JMeter客户端的机器性能不能满足测试需要,那么测试人员可以通过单个JMeter GUI客户端来控制多个远程JMeter服务器,以便对服务器进行压力测试,模拟 ...

  5. 杂项:UN-HTML

    ylbtech-杂项:HTML 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   1 ...

  6. loadrunner 学习 1 —— 关于loadrunner的安装/破解

    从网上下载了loadrunner 11, .iso格式的镜像文件,百度一下,发现要用专门的软件才能在windows7 下安装 iso,我选的是 软件魔方. 安装完破解时,略有曲折, 主要是要以管理员的 ...

  7. PHP中的精确计算bcadd,bcsub,bcmul,bcdiv

    引言:一定要确保数据的准确性.这是一个好的程序员的基本素养. <?php /** * 精确加法 * @param [type] $a [description] * @param [type] ...

  8. 360良心制作fonts.useso.com

    我们的网站,经常会用到google的一些数据. 但在国内无法使用google, 360这个良心的企业,解决了这个问题. 把google替换成useso就可以了. 比如, <link href=& ...

  9. DEV CheckComboboxEdit、CheckedListBoxControl(转)

    CheckComboboxEdit //先清空所有,若在窗体Load事件中,也可以不清空 //cbRWYs.Properties.Items.Clear(); var RwyList = tspro. ...

  10. http协议Keep-Alive

    Keep-Alive 是什么? 概观 默认情况下,HTTP链接通常在请求完成之后关闭.这意味着服务端在完成响应的交付之后便关闭了TCP链接.为了让链接保持打开,来满足多请求,可以使用keep-aliv ...