zoukankan      html  css  js  c++  java
  • Asp.Net高级知识回顾_HttpHandler

    一、概述:

    其实每个.aspx页面都是一个HttpHandler,因为System.Web.UI.Page类实现了IHttpHandler接口。一般情况下,响应客户端请求的都是.aspx页面,这时候System.Web.UI.Page类可以作出合适的处理。但有时候响应给客户端的不一定就是.aspx页面,有可能是XML或者图像等,这个时候就需要自定义HttpHandler进行处理。

    常用的HttpHandler处理有构造缩略图、图片加水印。一般在网站中,比如一个购物网站的商品列表里,显示的商品图片都是经过缩略处理。大家可以想象到,如果直接把原图返回到客户端显示,网络流量是如此巨大,这样会严重影响页面显示速度。同样,很多网站上的图像资源都是原创的,为了保证版权,防止不法盗用,都会在图片返回到客户端之前对图片进行处理,加上数字水印标记。为图片资源加上水印,可以防止原创图片被非法盗用,而且使用编程方式添加可以在不破坏原图的情况下对图片进行处理。

    HttpHandler与HttpModule区别:

    两者的区别:

    a. 先后次序:
    数据先经过HttpModule,再经过HttpHandler,然后又返回到HttpModule。注意,Module要判断响应的是哪个事件,有些事件是在Handler之前执行,有些是在Handler之后执行。

    b.对请求的处理:
    HttpModule无论客户端请求的是什么文件,它都会对请求进行拦截处理,例如.aspx,.rar,.html,.jpg等等的请求。HttpHandler只有在ASP.NET注册过的文件类型(例如aspx,asmx等等)才会调用它。

    c.HttpHandler是请求的最终处理中心,按照请求生成响应的内容。HttpModule对请求进行预处理,如验证、修改、过滤等等,同时也可以对响应进行处理。

    二、IHttpHandler

    IHttpHandler接口:定义ASP.NET为使用自定义Http处理程序同步处理Http Web请求而实现的协定。Http处理程序是实现了System.Web.IHttpHandler接口的.NET组件,接口是一种规范,因此任何实现了IHttpHandler接口的类都可以用于处理输入的Http请求。

    Http处理程序可分为同步处理程序、异步处理程序。同步处理程序必须继承IHttpHandler接口,异步处理程序必须继承IHttpAsyncHandler接口。

    public interface IHttpHandler
        {
            // 摘要:
            // 获取一个值,该值指示其他请求是否可以使用System.Web.IHttpHandler实例。
            // 返回结果:
            // 如果System.Web.IHttpHandler实例可再次使用,则为true;否则为false。
            bool IsReusable { get; }
    
            // 摘要:
            // 通过实现System.Web.IHttpHandler接口的自定义HttpHandler启用HTTP Web请求的处理。
            // 参数:
            // context:
            //  System.Web.HttpContext 对象,它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session、和Server)的引用。
            void ProcessRequest(HttpContext context);
        }
    1.0 IsReusable
    //IsReusable属性指定IHttpHandlerFactory对象(实际调用适当处理程序的对象)是否可以将处理程序放置在由CLR会维护的一个对象池中,并且重新使用它们以提高性能,或是否在每次需要处理程序时都必须创建新实例。如果IHttpHandler实例可再次使用,则为true,否则为false。
    //Page类上的IsReusable属性返回false,表示需要该Http请求的新实例来服务一个页面请求。通常我们使它在所有情况下都返回false,并根据请求负荷的不同而要求它做一些有意义的处理。那些不依赖于context.Request对象,也没有成员变量,被用作筛选特殊请求的简单屏障的处理程序可以将IsReusable设置为true,以节省一些系统资源。
    2.0 ProcessRequest
    //顾名思义,ProcessRequest就是请求响应,是Http请求的最终处理方法。一个Http请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理。方法中应该放置我们处理请求的主要代码。

    在ProcessRequest方法中,需要一个HttpContext类型的参数,这个参数也称为上下文。它封装有关个别 Http请求的所有Http特定的信息。在HttpContext对象中可以获得用于为Http请求提供服务的内部服务器对象(如Request、Response和Server)的引用。当客户端发送某个Http请求,我们可以通过HttpContext进行截获,查看里面所包含的请求信息,可以进行一系列的操作。

    下面以图片添加数字水印例子简述ProcessRequest方法的用法:

    首先创建HttpHandler处理类。在项目中添加一个实现了IHttpHandler接口的类,这里我们把HttpHandler处理类命名为“CoverHandler”。代码如下所示:

    using System;
    using System.Web;
    public class CoverHandler: IHttpHandler { 
     //需要继承IHttpHandler接口
          public CoverHandler()
        {
        }
        //水印图片路径
    private const string WATERMARK_URL = "~/Image/watermark.bmp";
    //默认图片路径
    private const string DEFAULTIMAGE_URL = "~/Image/default.bmp";
    public void ProcessRequest (HttpContext context) 
    {
        System.Drawing.Image Cover;
        //判断请求的物理路径中是否存在被请求的图片文件
        if (File.Exists(context.Request.PhysicalPath))
        {
            //加载图片文件
            Cover = Image.FromFile(context.Request.PhysicalPath);
            //加载水印图片
            Image watermark = Image.FromFile(context.Request.MapPath(WATERMARK_URL));
            //实例化画布
            Graphics g = Graphics.FromImage(Cover);
            //在image上绘制水印
            //Rectangle部分设置画的大小,图片根据它来缩放。后面的指定要用来画上去的图片,画那一部分。(起始点大小,代表载取的图片放到前面的指定大小里面去)
            g.DrawImage(watermark, new Rectangle(Cover.Width - watermark.Width, Cover.Height - watermark.Height, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel);
            //释放画布
            g.Dispose();
            //释放水印图片
             watermark.Dispose();
        }
        else
        {
            //如果被请求的图片不存在时,加载默认图片
            Cover = Image.FromFile(context.Request.MapPath(DEFAULTIMAGE_URL));
        }
        //设置输出格式
        cotext.Response.ContentType = "image/jpeg";
        //将图片存入输出流
        Cover.Save(context.Response.OutputStream, 
    System.Drawing.Imaging.ImageFormat.Jpeg);
        Cover.Dispose();
        context.Response.End();
    }
    
        public bool IsReusable 
        {
            get {
                return false;
            }
        }
    }

    三、全局配置HttpHandler

    要让系统自动捕获对图片访问的请求,需要在项目里Web.config配置文件中添加httpHandlers配置节进行配置。代码如下所示:

    <system.web>
        ......
    <httpHandlers>
             <add path="*.jpg" verb="*" validate="false" type="CoverHandler"/>
         </httpHandlers>
    </system.web>
    
    各项属性代表含义如下:
    path:必选属性。指定路径属性可以包含单个URL路径或简单的通配符字符串(如 *.aspx)。“*”为通配符。
    verb:必选的属性。指定谓词列表可以是逗号分隔的Http谓词列表(例如,“GET, PUT, POST”),也可以是开始脚本映射。“*”为通配符。
    validate:可选属性。如果为false,则ASP.NET在实际匹配请求到达之前将不尝试加载该类。这有可能延迟错误,但减少了启动时间。
    type:必选属性。指定逗号分隔的类/程序集组合。ASP.NET首先在应用程序的专用in目录中搜索程序集DLL,然后在系统程序集缓存中搜索程序集DLL。

    这样,当客户端发送访问jpg文件时,系统会自动截获请求转交给CoverHandler类处理。

    但要注意的是,使用这种配置方式,在开发服务器上运行时没有问题。但如果在IIS上运行(经典模式),将会没有任何效果。这是因为开发服务器仅提供最简单的Web服务器功能,它不对请求的内容做任何处理,而是直接将所有的请求转交给ASP.NET处理。IIS是一个比较完善且功能强大的Web服务器。所有提交到IIS的请求,会在IIS上做一些分类处理,所依据的原则就是后缀名。默认情况下,.html、.jpg等静态格式的文件IIS会自己处理,直接将结果返回到客户端。只有当后缀名符合相关条件的(如.aspx),才将请求转交给ASP.NET进行处理。

    也就是说IIS根本没有把请求提交给ASP.NET处理。因此我们需要对IIS作配置。

    打开IIS信息服务管理器,在IIS栏目下打开“处理程序映射”功能。

    可以看到不同后缀名的请求对应不同的处理程序。点击界面右侧“添加脚本映射”。

    填写相关内容后点击“确定”,新的映射添加成功,并出现在映射列表中

    这样当客户端请求的内容带有.jpg后缀名时,IIS即会把该请求转交给ASP.NET处理。达到返回的是带水印的图片。

    四、局部调用HttpHandler

    如果不需要对全部图片资源都添加数字水印,可以不采用上一节中说到的全局配置HttpHandler处理类的方式,而是使用一般处理程序对图片资源进行处理。

    选中项目点击右键,选择“添加新项”,选择“一般处理程序”,这里我们把一般处理程序命名为“PictureWaterMark”。系统创建的PictureWaterMark.ashx一般处理程序代码;代码跟我们上面的基本一致,多了一个接受图片路径参数的,

     string covername = context.Request.QueryString["covername"];调用的时候,可以:

    <asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("covername", "~/ PictureWaterMark.ashx?covername={0}") %>' />

    全局配置与局部调用HttpHandler两种方式各有优缺点,全局的配置是全面覆盖的,无论在哪个页面访问图片都被加上水印,而局部调用一般处理程序的方式只会在指定的访问时才加水印,它的使用比较灵活,但不便于维护。在开发过程中可以根据实际需求情况考虑使用那一种方式。

    五、HttpHandler访问Session

    在HttpHandler处理程序中,虽然ProcessRequest中有HttpContext对象,但在这里context对象却不能访问Session对象,使开发变得非常不方便。为了使HttpHandler处理程序能够访问Session对象,在类中除了继承IHttpHandler接口外,还需要引用System.Web.SessionState命名空间,并实现接口IReadOnlySessionStateIRequiresSessionState

    如果要在HttpHandler中读取Session的内容,就要实现IReadOnlySessionState 这个接口。

    如果要在HttpHandler中读写Session的内容,就要实现IRequiresSessionState这个接口。

    这两个接口没有需要实现的方法,可直接使用。两个接口的声明如下所示:

    IRequiresSessionState接口:
    namespace System.Web.SessionState
    {
        // 摘要:
        // 指定目标 HTTP 处理程序需要对会话状态值具有读写访问权。这是一个标记接口,没有任何方法。
        public interface IRequiresSessionState
        {
        }
    }
    IReadOnlySessionState接口:
    namespace System.Web.SessionState
    {
        // 摘要:
        // 指定目标 HTTP 处理程序只需要具有对会话状态值的读访问权限。这是一个标记接口,没有任何方法。
        public interface IReadOnlySessionState : IRequiresSessionState
        {
        }
    }
    这里能看到,其实IReadOnlySessionState接口是继承了IRequiresSessionState接口。

     

     

     

     

  • 相关阅读:
    在HTML中使用JavaScript
    七层网络模型
    JS执行机制
    继承
    变量作用域
    跨域
    ES6-Promise
    回调函数
    2019.3.9笔试
    CSS3新特性
  • 原文地址:https://www.cnblogs.com/entclark/p/8647845.html
Copyright © 2011-2022 走看看