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方法)