原文地址: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. Python学习系列(七)( 数据库编程)

    Python学习系列(七)( 数据库编程)        Python学习系列(六)(模块) 一,MySQL-Python插件       Python里操作MySQL数据库,需要Python下安装访 ...

  2. simple_one_for_one 和 one_for_one的区别

    参考这里http://blog.sina.com.cn/s/blog_77cb45a70102v1ja.html 用起来最直观的不同点 simple_one_for_one需要手工start_chil ...

  3. AngularJS:模型

    ylbtech-AngularJS:模型 1.返回顶部 1. AngularJS ng-model 指令 ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, ...

  4. Idea 如何设置微软雅黑等其它字体

    使用过idea的同学都知道,idea的功能相对于explise来说,功能太强大了啊~个人感觉,idea真心挺智能的.但是,这里有一个小瑕疵,就是能够设置的字体,有限! 对于用惯了 微软雅黑 字体的人, ...

  5. MFC调试的几个技巧

    TCHAR pStr[] = _T("this is a test!"); void* p = (void*)pStr; TRACE(_T("pStr is %s\n&q ...

  6. Ehcache入门介绍一

    EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. 特性有: 1. 快速轻量 Ehcache的线程机制是为大型高并发系统设 ...

  7. Hadoop入门介绍一

    Hadoop1.是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储.2.Hadoop实现了一个分布式文件 ...

  8. chkdsk工具怎么修复

    对于一些硬盘存储问题,即使windows自带的系统工具,也可以将其修复,比如chkdsk程序.请阅读下文,了解如何使用chkdsk来修复简单的硬盘问题. 工具/原料 windows7 chkdsk 方 ...

  9. openstack 租户ip 手动配置 openstack静态租户ip

    作者:[吴业亮]云计算开发工程师 博客:http://blog.csdn.net/wylfengyujiancheng 1.综述: 在日常开发和生产环境中经常需要将OpenStack虚拟机配置一个静态 ...

  10. leetcode592

    public class Solution { private int GCD(int a, int b) { ? GCD(b, a % b) : a; } private int LCM(int a ...