Asp.Net高级知识回顾_HttpHandler

本文详细介绍了自定义HttpHandler的应用场景和技术细节,包括构造缩略图、图片加水印等功能的实现方法。此外,还讲解了如何配置HttpHandler以及如何在处理程序中访问Session。

一、概述:

其实每个.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首先在应用程序的专用\bin目录中搜索程序集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接口。

 

 

 

 

 

 

转载于:https://www.cnblogs.com/entclark/p/8647845.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值