HttpHandler

什么是HttpHandler?平时所创建的ASP.NET页面即System.Web.UI.Page类就是一个HttpHandler,因为它实现了IHttpHandler接口.
     HttpHandler就是最终响应Http请求,生成Http响应的处理器.它的实例由ASP.NET运行时创建,并生存在ASP.NET运行时环境中.如把ASP.NET运行时比作处理请求的工厂,HttpHandler就是处理请求的工人.
     什么情况下自定义HttpHandler呢?一般来说我们响应给客户端的都是一个HTML页面,这种情况下,System.Web.UI.Page这个默认的HttpHandler就完全可以胜任,但有时我们响应给客户端的不是一个HTML页面,而是XML数据或者图片等,这时使用自定义的HttpHandler可能是更好的选择.
     HttpContext 类:封装有关个别 HTTP 请求的所有 HTTP 特定的信息。
    为继承 IHttpModule 和 IHttpHandler 接口的类提供了对当前 HTTP 请求的 HttpContext 对象的引用。该对象提供对请求的内部 Request、Response 和 Server 属性的访问。

    这是我补充的HttpContext 类:
    1.生存周期:从客户端用户点击并产生了一个向服务器发送请求开始---服务器处理完请求并生成返回到客户端为止.
       注:针对每个不同用户的请求,服务器都会创建一个新的HttpContext实例直到请求结束,服务器销毁这个实例.
    2.为什么会有HttpContext类呢:在ASP年代,大家都是通过在.asp页面的代码中使用Request,Respose,Server等等这些Http特定信息的.但在ASP.NET时代,这中方式已经无法满足应用,(比如我们要在IHttpModule中处理Request时,我们使用什么方法来获取呢?于是就产生了HttpContext类,它对Request,Respose,Server等等都进行了封装,并保证在整个请求周期内都可以随时随地的调用.)
    3.特殊性:当然HttpContext不仅仅只有这点功能.ASP.NET中它还提供了很多特殊的功能.例如Cache.还有HttpContext.Item,通过它你可以在HttpContext的生存周期内提前存储一些临时的数据,方便随时使用.

HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
IHttpHandler是什么
IHttpHandler定义了如果要实现一个HTTP请求的处理所必需实现的一些系统约定。HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。
IHttpHandler如何处理HTTP请求
当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。
对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。所谓一个HttpHandlerFactory,所谓一个HttpHandlerFactory,是指当一个HTTP请求到达这个HttpHandler Factory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。
一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。
一个简单的HttpHandler容器
通过实现IHttpHandler接口可以创建自定义HTTP处理程序,该接口只包含两个方法。通过调用IsReusable,IHttpHandlerFactory可以查询处理程序以确定是否可以使用同一实例为多个请求提供服务。ProcessRequest方法将HttpContext实例用作参数,这使它能够访问Request和Response内部对象。在一个HttpHandler容器中如果需要访问Session,必须实现IRequiresSessionState接口,这只是一个标记接口,没有任何方法。
示例1:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.SessionState;

namespace MyHandler
{
    /// <summary>
    /// 目的:实现一个简单的自定义HttpHandler容器
    /// </summary>
    public class MyFirstHandler : IHttpHandler,IRequiresSessionState
    {
        #region IHttpHandler 成员

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write("<h1><b>Hello HttpHandler</b></h1>");
            context.Session["Test"] = "测试HttpHandler容器中调用Session";
            context.Response.Write(context.Session["Test"]);
        }

        #endregion
    }
}
在Web.config中加入如下配置:
< httpHandlers >
     <add verb="*" path="*" type="MyHandler.MyFirstHandler, MyHandler"/>
</httpHandlers>

IHttpHandler工厂
ASP.NET Framework实际不直接将相关的页面资源HTTP请求定位到一个其内部默认的IHttpHandler容器之上,而定位到了其内部默认的IHttpHandler工厂上。IHttpHandler工厂的作用是对IHttpHandler容器进行调度和管理。
IHttpHandlerFactory接口包含两个方法。GetHandler返回实现IHttpHandler接口的类的实例,ReleaseHandler使工厂可以重用现有的处理程序实例。
示例2:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace MyHandler
{
    public class MyHandlerFactory : IHttpHandlerFactory
    {
        #region IHttpHandlerFactory 成员

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            string fname = url.Substring(url.IndexOf('/') + 1);
            while (fname.IndexOf('/') != -1)
                fname = fname.Substring(fname.IndexOf('/') + 1);
            string cname = fname.Substring(0, fname.IndexOf('.'));
            string className = "MyHandler." + cname;

            object h = null;

            try
            {
                // 采用动态反射机制创建相应的IHttpHandler实现类。
                h = Activator.CreateInstance(Type.GetType(className));
            }
            catch (Exception e)
            {
                throw new HttpException("工厂不能为类型"+cname+"创建实例。",e);
            }

            return (IHttpHandler)h;
        }

        public void ReleaseHandler(IHttpHandler handler)
        {
           
        }

        #endregion
    }

    public class Handler1 : IHttpHandler
    {
        #region IHttpHandler 成员

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write("<html><body><h1>来自Handler1的信息。</h1></body></html>");
        }

        #endregion
    }

    public class Handler2 : IHttpHandler
    {
        #region IHttpHandler 成员

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write("<html><body><h1>来自Handler2的信息。</h1></body></html>");
        }

        #endregion
    }
}

<httpHandlers>
      <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/>
      <add verb="*" path="*.html" type="MyHandler.MyFirstHandler, MyHandler"/>
      <add verb="*" path="*.htm" type="ImageHandler, ImageHandler"/>
</httpHandlers>

posted on 2008-12-05 10:46  青春的虎子  阅读(1040)  评论(0编辑  收藏  举报

导航