原文地址: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. lbypmall系统备份恢复

    打开phpmyadmin 1.数据库创建,在服务器上创建lbypmall数据库,排序规则utf8_general_ci 2.mysqldump -u root -p lbypmall > lby ...

  2. vs2003属性窗口空白的问题

    一个困扰很久的问题一直没有解决,因为vs的属性窗口没显示不方便修改mfc程序的id和属性等等,但是可以直接在代码里修改.问题始终是问题,最近准备画时间解决之,上网差资料搜索办法,一帖说是win7的问题 ...

  3. 安装S_S相关报错的troubleshooting

    在安装S_S server时,在Debian上会出现类似如下的报错: File , in <module> sys.exit(main()) File , in main config = ...

  4. (转)WebApi发送HTML表单数据:文件上传与多部分MIME

    5.3 Sending HTML Form Data5.3 发送HTML表单数据(2) 本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/282 ...

  5. Spring security 浅谈用户验证机制

    step1:首先ApplicationUserDetailsService需要实现UserDetailsService接口(在 org.springframework.security.core.us ...

  6. 【转】Jmeter在命令行运行技巧

    For non-interactive testing, you may choose to run JMeter without the GUI. To do so, use the followi ...

  7. 面向对象银角大王补充2-self就是调用当前方法的对象-静态字段,公有属性-封装的理解-继承的理解,普通方法,静态方法

    self是什么,就是一个函数,就是一个形式参数 4.self就是调用当前方法的对象 静态字段,公有属性 静态字段使用场景,每个对象中保存相同的东西时,可以使用静态字段,公有属性 5.封装的理解 类中封 ...

  8. python开发socket套接字:粘包问题&udp套接字&socketserver

    一,发生粘包 服务器端 from socket import * phone=socket(AF_INET,SOCK_STREAM) #套接字 phone.setsockopt(SOL_SOCKET, ...

  9. C++11 变量和函数的链接性

    在全局变量前添加const或者static,则该变量链接性为内部,即文件内有效.可以使用extern声明为外部. 如果要让函数的链接性为内部,则函数声明和定义都应使用static关键字. 例子: te ...

  10. 01CSS的引入方式

    引入CSS方式(重点掌握) 行内样式 内接样式 外接样式 链接式 导入式 css介绍 现在的互联网前端分三层: HTML:超文本标记语言.从语义的角度描述页面结构. CSS:层叠样式表.从审美的角度负 ...