玩.Net 的人都知道,服务器对一个web请求的处理过程封装在一个叫做处理管道的“黑匣子”里面,这个“黑匣子”里面有很多针对一次请求处理的事件,其中微软只暴露出19个给我们程序猿使用(小弟下篇博文会对这个“黑匣子”进行个简单的整理)。19个事件中我们其实是可以通过事件注册来让它做我们想做的事,本文就简单来啰嗦下这个话题。
一个动态的url请求到达IIS服务器之后,首先接待它的是HttpRuntime,该类很庞大,负责对一次完整请求的所有处理。因为一次处理过程其实是相当艰辛的,它一个人忙不过来,于是找HttpContext和HttpApplication两个伙计来帮忙而且两人各有分工,HttpContext主要封装了原始的请求报文,还有几个得力助手,比较出名的是Response、Request、Server几人,分别负责向浏览器输出、获取浏览器请求参数、服务器端的一些助手类工作。而那个处理管道也就是19个事件在哪里呢?就是在HttpApplication这个类中,HttpApplication和HttpContext两个类也是密不可分的,就好像HttpContext是原料厂,HttpApplication是对原始材料进行处理加工的生产厂(这些都是对HttpModule进行处理的基本储备知识)
本着低耦合高内聚的经典设计思想,我先在项目中见一个类库项目MyHttpModule,里面建类RegModule。由上面知识点的罗列可以想到,如果要在RegModule类中对处理管道中的事件进行注册的话,这个类必须包含HttpApplication、HttpContext这些东东才行,因为那些事件是在HttpApplication里的嘛,所以它必须实现一个叫做IHttpModule的接口,该接口在命名空间system.web下,接口定义如下:
namespace System.Web
{
// 摘要:
// 向实现类提供模块初始化和处置事件。
public interface IHttpModule
{
// 摘要:
// 处置由实现 System.Web.IHttpModule 的模块使用的资源(内存除外)。
void Dispose();
//
// 摘要:
// 初始化模块,并使其为处理请求做好准备。
//
// 参数:
// context:
// 一个 System.Web.HttpApplication,它提供对 ASP.NET 应用程序内所有应用程序对象的公用的方法、属性和事件的访问
void Init(HttpApplication context);
}
}
熟悉的HttpApplication作为该接口的Init方法参数出现,是不是让你有点兴奋?
在RegModule中实现IHttpModule中的方法,代码如下:
class RegModule:IHttpModule
{
public void Dispose()
{
throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
throw new NotImplementedException();
}
}
在Init方法里,作为HttpApplication类型的context参数,便具有了处理管道中的那些个事件。既然是事件就可以通过delegate来注册吧(关于delegate的使用细节不再赘述),先来个简单的,对BegainRequest这个处理一开始第一个执行的事件进行注册,主要代码如下:
public void Init(HttpApplication context)
{
//throw new NotImplementedException();
context.BeginRequest+=new EventHandler(context_BeginRequest);
}
public void context_BeginRequest(object sender, EventArgs e)
{
}
到这里,其实你应该看出来了,参数sender就代表HttpContext,使用as关键字将它打回原形,就可以调用context里的Write、SetCookie等等那些个方法了,我就简单的输出一句话有个意思就行,代码:(sender as HttpContext).Response.Write("Hello,你知道我是从哪里来的吗?");
至此,在这个类中对Module的注册就算是完成了,那么怎么在你的web程序中使用呢?有两点,首先肯定要引用当前类库;其次在config文件中添加<Httpmodule>配置节。添加配置代码如下:
<system.web>
<compilation debug="false" targetFramework="4.0" />
<httpModules>
<add name="myHttpModule" type="MyHttpModule.RegModule,MyHttpModule"/>
</httpModules>
</system.web>
name随便起,type中有两部分用逗号隔开,前面是注册Module的命名空间.类名,后面其实是引用的程序集名,我当前默认程序集名与类名相同了。完成这些之后添加个aspx页面测试一把,直接空页面进行浏览
是不是很爽呢……哈哈