说实话,本人不才,一直没理解HttpModule到底是什么,今天看页面的管道事件,突然有了点顿悟于是就写下来
首先:
1. HttpHandler泛指所有实现IHttpHandler接口的类型。(使用HttpHanlder的目的是生成响应结果)
2. HttpModule泛指所有实现IHttpModule接口的类型。(设置所有请求)
为什么HttpModule可以设置所有请求呢?
如果要了解HttpHandler和HttpModule以及HttpApplication那就首先要了解浏览器请求服务器的整个周期,
在此我不过多的介绍生命周期的东西,主要从请求请求到达托管环境之后开始介绍,因为我今天主要想介绍的是HttpHandler和HttpModule,不想偏题
请求是怎么通过非托管环境到达托管环境的呢?
首先我们要知道aspnet_isapi.dll
aspnet_isapi.dll:负责启动aspnet 运行的环境,并作初始化操作。另外将当前请求分发给ISAPIRuntime处理
在托管环境中:我们看下ISAPIRuntime都做了什么事情?
通过Reflector(下图除非特别说明都是来自Reflector)
*****************************华丽丽的分割线********************************
查看ISAPIRuntime类
在ISAPIRuntime类中有个PR方法:有一个参数是ecb句柄,请求从非托管环境到达托管环境主要是通过它,因为请求本身并不会从非托管环境到达托管环境,这个ecb句柄就像是一个函数指针,它指向非托管环境下的请求
在这个PR(ProcessRequest)方法里微软都帮我们做了什么呢?我们通过我们的Reflector继续往下看
在HttpRuntime的PR方法里微软又给我们做了什么呢?我们继续
看微软帮我们做了什么,没错,这就是我们的上下文context对象
在HttpRuntime的PR方法中它还调用了
在ProcessRequestNoDemand(wr);方法中调用了 ProcessRequestNow(wr)方法
在 ProcessRequestNow(wr);中有一个ProcessRequestInternal方法
在 ProcessRequestInternal方法里,
这里给我们创建了一个实现IHttpHandler接口的HttpApplication实例,仔细看这个实例是由通过HttpApplicationFactory(是个工厂
?我们去看下)的GetApplicationInstance(context)方法创建的,
在方法GetApplicationInstance中,有一个在GetApplicationInstance(context);中
这里说一下怎么获取HttpApplication对象
1:池子有就立即返回
2:池子没有:把Gloable文件编译类型反射出一个实例出来。
HttpApplication.state.InitInternal(context, this._state, this._eventHandlerMethods);
注意到最后一个参数是this._eventHandlerMethods,这就是global.asax中的各个EventHandler。InitInternal方法也是一个比较复杂的方法,里面对于IIS采用的是Integrated模式还是Classic模式进行分别的处理,主要完成的工作时HttpModule的初始化和处理请求过程中每个步骤触发事件处理程序的准备。先看Integrate模式下Module的初始化: 把所有的HttpModule从配置文件中读取出来并创建到HttpModule的一个集合里面去。然后遍历此集合,把集合中的所有的HttpModule的Init方法调用并传当前HttpApplication实例的到方法方法里面去。一般情况下HttpModule的Init方法内部就是注册HttpApplication的管道事件响应方法。
在 this.InitIntegratedModules();
第一根据配置的module名字,初始化module对象到一个集合里
在this.InitModulesCommon();中做了什么呢?
private void InitModulesCommon() { int count = this._moduleCollection.Count; for (int i = 0; i < count; i++)//循环遍历module对象集合 { this._currentModuleCollectionKey = this._moduleCollection.GetKey(i); this._moduleCollection[i].Init(this);//调用它的init方法 } this._currentModuleCollectionKey = null; this.InitAppLevelCulture(); }
所以如果实现了IHttpModule接口,在起Init方法里写的代码都会被执行,所以可以在init里面注册事件, 如果想设置所有的请求,可使用HttpModule,比如(页面输出压缩)
HttpHandler可以注册的是Asp.Net管道里第11和12个事件之间执行的Asp.Net管道里第7.8个事件之间创建的IHttpHandler实例的PR方法
为什么HttpHandler可以过滤一类特定的请求,
因为HttpHandler的是第7.8个事件之间根据请求页面创建的一个实例,有针对性,如果想要对过滤出来某一类页面进行操作,就需在写一个继承IHttpHandler的类(里面对需处理的页面进行操作),然后需要进行过滤的页面就继承这个类,这样如果你请求的页面继承了你写的那个类,在HttpHandler的是第7.8个事件之间根据请求创建IHttpHandler的实例的时候,就是创建的你写的那个实例,到11,12之间执行IHttpHandlerPR方法里和你自己类写的名字相同方法的时候就是你自己写的类的方法了