asp.net HttpModule和HttpApplication 用法(1/3)
ihttpmodule是个什么东西呢?对我们web开发有什么用呢?
先从名字来看他是一个接口,接口就是让人来继承的,我们要用它就得继承他,并实现他的方法。module的意思是模块、组件的意思。如果说我们实现了这个接口,并配置了web.config,让iis的知道我们的web程序使用了这个组件;那么我们的程序是不是就比默认的web程序多了个组件?!显然,而且在必要的时候会调用我们组件里定义的方法,这就是httpmodule的用处。说白了,就是我们给iis写扩展,但该扩展仅仅是针对于使用了(配置config)的web程序。其实每个web应用程序都是一个iis进程,而这个进程的配置文件就是web.config。
弄明白了他的意义,我们就开始!我们创建一个web应用程序,并创建一个类,继承ihttpmodule,并实现他的方法,在config的modules节点里<add name="" type=""/>,ok!
namespace webapplication1
{
public class myhttpmodule : ihttpmodule
{
public void dispose()
{
}public void init(httpapplication context)
{
context.context.response.write(1);
}
}
}
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetframework="4.0" />
<httpmodules>
<add name="myhttpmodule" type="webapplication1.myhttpmodule,webapplication1"/>
</httpmodules>
</system.web><system.webserver>
<modules runallmanagedmodulesforallrequests="true">
<add name="myhttpmodule" type="webapplication1.myhttpmodule,webapplication1"/><!--注意:type="类的fullname,类所在的dll名"-->
</modules>
</system.webserver>
</configuration>
web.config的配置有2个,上面的那个是给非iis7用的,下面的显然就是给iis7用的。启动程序,what happend?! 是不是页的头部多了个1,有木有!!我们打开任何页面都会有个1,说明我们的模块起到作用了,也说明每个请求都会执行httpmodule的init方法?是不是呢?
我们把代码改一下:
public void init(httpapplication context)
{
context.context.response.write(1);
context.beginrequest += onbeginrequest;
}public void onbeginrequest(object sender, eventargs e)
{
var app = (httpapplication)sender;
var url = app.context.request.rawurl;
app.context.response.write(url);
}
分别给init和onbeginrequest 两个方法加断点,重新编译下,然后f5看看。init只走1次,而onbeginrequest却走了3次,ur的值l分别是 default.asp教程x style.css教程 和 favorite.ico;可以看出任何url请求,包括静态文件,都会经过执行我们定义的事件方法!看来这要比只处理aspx慢不少!
init的必须走一次啊,要不然事件不被订阅3次了?,但为什么只走1次呢?这到底是为什么呢? 呵呵,其实很简单,myhttpmodule就实例化一次哦,实例化后执行init初始化,然后就驻留在应用程序池了,直到应用程序池被回收,或他被各种原因搞崩溃;而onbeginrequest是被httpapplication类的beginrequest事件订阅的。事件订阅是个什么概念?事件是个特殊的委托,委托是个什么概念?委托是个方法指针。所以,只要委托被执行,就会执行他指向的方法体,也就是onbeginrequest,可见onbeginrequest的执行,是和httpapplication的beginrequest有关系的,和myhttpmodule本身已经没关系了。
走了3次说明3个request都执行了beginrequest,难道每个请求都实例化一个httpapplication?从名字我就能看出不会的,因为application(应用程序)嘛,我们目前运行的就一个,怎么会不断的实例化!想刨根问题,彻底整明白,就得翻出framework的源码,调试!
(------------声明,下面的源码可以不用完全理解,也可以跳过,只要知道跟request有关就行了------------)
下面来调查下httpapplication的初始化过程!
用reflector查阅system.web名字空间下的类,可以看到httpapplicationfactory类,他负责httpapplication的创建。当我们启动站点后,第一次的时候比较慢,为什么呢? 因为初始化的构建工作。
system.web.complilation名字空间下有一堆的构建类,其中就有构建global.asax的,也就是我们的httpapplication类,然后缓存到factory的堆栈里,我们需要的时候pop出来。 (你可能有疑问,pop了不就没了吗? 其实app在执行的时候还会push回去,详见httpapplication.releaseappinstance方法)
补充:asp.net教程,.Net开发