httpModules 与 httpHandlers
httpModules 與 httpHandlers
ASP.NET對(duì)請(qǐng)求處理的過(guò)程:
當(dāng)請(qǐng)求一個(gè)*.aspx文件的時(shí)候,這個(gè)請(qǐng)求會(huì)被inetinfo.exe進(jìn)程截獲,它判斷文件的后綴(aspx)之后,將這個(gè)請(qǐng)求轉(zhuǎn)交給ASPNET_ISAPI.dll,ASPNET_ISAPI.dll會(huì)通過(guò)http管道(Http PipeLine)將請(qǐng)求發(fā)送給ASPNET_WP.exe進(jìn)程,在ASPNET_WP.exe進(jìn)程中通過(guò)HttpRuntime來(lái)處理這個(gè)請(qǐng)求,處理完畢將結(jié)果返回客戶(hù)端。
????inetinfo.exe進(jìn)程:是www服務(wù)的進(jìn)程,IIS服務(wù)和ASPNET_ISAPI.DLL都寄存在此進(jìn)程中。
????ASPNET_ISAPI.DLL:是處理.aspx文件的win32組件。其實(shí)IIS服務(wù)器是只能識(shí)別.html文件的,當(dāng)IIS服務(wù)器發(fā)現(xiàn)被請(qǐng)求的文件是.aspx文件時(shí),IIS服務(wù)器將其交給aspnet_isapi.dll來(lái)處理。
????aspnet_wp.exe進(jìn)程:ASP.NET框架進(jìn)程,提供.net運(yùn)行的托管環(huán)境,.net的CLR(公共語(yǔ)言運(yùn)行時(shí))就是寄存在此進(jìn)程中。
ASP.NET Framework處理一個(gè)Http Request的流程:
??? HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
ASP.NET請(qǐng)求處理過(guò)程是基于管道模型的,這個(gè)管道模型是由多個(gè)HttpModule和HttpHandler組成,ASP.NET把http請(qǐng)求依次傳遞給管道中各個(gè)HttpModule,最終被HttpHandler處理,處理完成后,再次經(jīng)過(guò)管道中的HTTP模塊,把結(jié)果返回給客戶(hù)端。我們可以在每個(gè)HttpModule中都可以干預(yù)請(qǐng)求的處理過(guò)程。
?
?
注意:在http請(qǐng)求的處理過(guò)程中,只能調(diào)用一個(gè)HttpHandler,但可以調(diào)用多個(gè)HttpModule。?
當(dāng)請(qǐng)求到達(dá)HttpModule的時(shí)候,系統(tǒng)還沒(méi)有對(duì)這個(gè)請(qǐng)求真正處理,但是我們可以在這個(gè)請(qǐng)求傳遞到處理中心(HttpHandler)之前附加一些其它信息,或者截獲的這個(gè)請(qǐng)求并作一些額外的工作,也或者終止請(qǐng)求等。在HttpHandler處理完請(qǐng)求之后,我們可以再在相應(yīng)的HttpModule中把請(qǐng)求處理的結(jié)果進(jìn)行再次加工返回客戶(hù)端。
HttpModule
??? HTTP模塊是實(shí)現(xiàn)了System.Web.IhttpModule接口的類(lèi)。
??? IHttpModule接口的聲明:
????????public interface IHttpModule
??????? {
??????????? void Init (HttpApplication context);
??????????? void Dispose ();
??????? }
????????Init 方法:系統(tǒng)初始化的時(shí)候自動(dòng)調(diào)用,這個(gè)方法允許HTTP模塊向HttpApplication 對(duì)象中的事件注冊(cè)自己的事件處理程序。
??????? Dispose方法: 這個(gè)方法給予HTTP模塊在對(duì)象被垃圾收集之前執(zhí)行清理的機(jī)會(huì)。此方法一般無(wú)需編寫(xiě)代碼。
????
??? HTTP模塊可以向System.Web.HttpApplication對(duì)象注冊(cè)下面一系列事件:
????????AcquireRequestState?當(dāng)ASP.NET運(yùn)行時(shí)準(zhǔn)備好接收當(dāng)前HTTP請(qǐng)求的對(duì)話(huà)狀態(tài)的時(shí)候引發(fā)這個(gè)事件。?
????????AuthenticateRequest?當(dāng)ASP.NET 運(yùn)行時(shí)準(zhǔn)備驗(yàn)證用戶(hù)身份的時(shí)候引發(fā)這個(gè)事件。?
????????AuthorizeRequest?當(dāng)ASP.NET運(yùn)行時(shí)準(zhǔn)備授權(quán)用戶(hù)訪(fǎng)問(wèn)資源的時(shí)候引發(fā)這個(gè)事件。?
????????BeginRequest?當(dāng)ASP.NET運(yùn)行時(shí)接收到新的HTTP請(qǐng)求的時(shí)候引發(fā)這個(gè)事件。?
????????Disposed?當(dāng)ASP.NET完成HTTP請(qǐng)求的處理過(guò)程時(shí)引發(fā)這個(gè)事件。?
????????EndRequest?把響應(yīng)內(nèi)容發(fā)送到客戶(hù)端之前引發(fā)這個(gè)事件。?
????????Error?在處理HTTP請(qǐng)求的過(guò)程中出現(xiàn)未處理異常的時(shí)候引發(fā)這個(gè)事件。?
????????PostRequestHandlerExecute?在HTTP處理程序結(jié)束執(zhí)行的時(shí)候引發(fā)這個(gè)事件。?
????????PreRequestHandlerExecute?在ASP.NET開(kāi)始執(zhí)行HTTP請(qǐng)求的處理程序之前引發(fā)這個(gè)事件。在這個(gè)事件之后,ASP.NET 把該請(qǐng)求轉(zhuǎn)發(fā)給適當(dāng)?shù)腍TTP處理程序。?
????????PreSendRequestContent?在ASP.NET把響應(yīng)內(nèi)容發(fā)送到客戶(hù)端之前引發(fā)這個(gè)事件。這個(gè)事件允許我們?cè)趦?nèi)容到達(dá)客戶(hù)端之前改變響應(yīng)內(nèi)容。我們可以使用這個(gè)事件給頁(yè)面輸出添加用于所有頁(yè)面的內(nèi)容。例如通用菜單、頭信息或腳信息。?
????????PreSendRequestHeaders?在ASP.NET把HTTP響應(yīng)頭信息發(fā)送給客戶(hù)端之前引發(fā)這個(gè)事件。在頭信息到達(dá)客戶(hù)端之前,這個(gè)事件允許我們改變它的內(nèi)容。我們可以使用這個(gè)事件在頭信息中添加cookie和自定義數(shù)據(jù)。?
????????ReleaseRequestState?當(dāng)ASP.NET結(jié)束所搜有的請(qǐng)求處理程序執(zhí)行的時(shí)候引發(fā)這個(gè)事件。?
????????ResolveRequestCache?我們引發(fā)這個(gè)事件來(lái)決定是否可以使用從輸出緩沖返回的內(nèi)容來(lái)結(jié)束請(qǐng)求。這依賴(lài)于Web應(yīng)用程序的輸出緩沖時(shí)怎樣設(shè)置的。?
????????UpdateRequestCache?當(dāng)ASP.NET完成了當(dāng)前的HTTP請(qǐng)求的處理,并且輸出內(nèi)容已經(jīng)準(zhǔn)備好添加給輸出緩沖的時(shí)候,引發(fā)這個(gè)事件。這依賴(lài)于Web應(yīng)用程序的輸出緩沖是如何設(shè)置的。
??? 上面這么多的事件,我們看起來(lái)可能會(huì)有些眼暈,但沒(méi)關(guān)系,下面一步一步地看。
??? HttpModule生命周期示意圖
?
下面是事件的觸發(fā)順序:
?
BeginRequest和PreRequestHandlerExecute之間的事件是在服務(wù)器執(zhí)行HttpHandler處理之前觸發(fā)。
??? PostRequestHandlerExecute和PreSendRequestContent之間的事件是在服務(wù)器執(zhí)行Handler處理之后觸發(fā)。
?
?
?
?下面我們看一下如何使用HttpModule來(lái)實(shí)現(xiàn)我們?nèi)粘5膽?yīng)用:
??????? HttpModule通過(guò)在某些事件中注冊(cè),把自己插入ASP.NET請(qǐng)求處理管道。當(dāng)這些事件發(fā)生的時(shí)候,ASP.NET調(diào)用對(duì)相應(yīng)的HTTP模塊,這樣該模塊就能處理請(qǐng)求了。
???????1、向每個(gè)頁(yè)面動(dòng)態(tài)添加一些備注或說(shuō)明性的文字:
??????????? 有的網(wǎng)站每一個(gè)頁(yè)面都會(huì)彈出一個(gè)廣告或在每個(gè)頁(yè)面都以注釋形式(<!-- -->)加入網(wǎng)站的版權(quán)信息。如果在每個(gè)頁(yè)面教編寫(xiě)這樣的JS代碼的話(huà),對(duì)于大一點(diǎn)的網(wǎng)站,這種JS代碼的編寫(xiě)與維護(hù)可是一個(gè)很繁瑣枯燥的工作。
??????????? 有了HttpModule我們就可以很簡(jiǎn)單地解決這個(gè)問(wèn)題了。HttpModule是客戶(hù)端發(fā)出請(qǐng)求到客戶(hù)端接收到服務(wù)器響應(yīng)之間的一段必經(jīng)之路。我們完全可以在服務(wù)器處理完請(qǐng)求之后,并在向客戶(hù)端發(fā)送響應(yīng)文本之前這段時(shí)機(jī),把這段注釋文字添加到頁(yè)面文本之后。這樣,每一個(gè)頁(yè)面請(qǐng)求都會(huì)被附加上這段注釋文字。
??????????? 這段代碼究竟該在哪個(gè)事件里實(shí)現(xiàn)呢? PostRequestHandlerExecute和PreSendRequestContent之間的任何一個(gè)事件都可以,但我比較喜歡在EndRequest事件里編寫(xiě)代碼。
????????????第一步:創(chuàng)建一個(gè)類(lèi)庫(kù)ClassLibrary831。
??????????? 第二步:編寫(xiě)一個(gè)類(lèi)實(shí)現(xiàn)IHttpModule接口
????????????????class TestModule:IHttpModule
??????????????? {
??????????????????? public void Dispose()
??????????????????? {
??????????????????? }
??????????????????? public void Init(HttpApplication context)
??????????????????? {
??????????????????? }
??????????????? }?
??????????? 第三步:在Init事件中注冊(cè)EndRequest事件,并實(shí)現(xiàn)事件處理方法
???????????????class TestModule:IHttpModule
??????????????? {
??????????????????? public void Dispose(){}
??????????????????? public void Init(HttpApplication context)
??????????????????? {
????????????????????????context.EndRequest += new EventHandler(context_EndRequest);
??????????????????? }
????????????????????void context_EndRequest(object sender, EventArgs e)
??????????????????? {
??????????????????????? HttpApplication ha = (HttpApplication)sender;
??????????????????????? ha.Response.Write("<!--這是每個(gè)頁(yè)面都會(huì)動(dòng)態(tài)生成的文字。--grayworm-->");
??????????????????? }
??????????????? }?
??????????? 第四步:在Web.Conofig中注冊(cè)一下這個(gè)HttpModule模塊
??????????<httpModules>
???????????<add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>
????????? </httpModules>?
????????? name:模塊名稱(chēng),一般是類(lèi)名
????????? type:有兩部分組成,前半部分是命名空間和類(lèi)名組成的全名,后半部分是程序集名稱(chēng),如果類(lèi)是直接放在App_Code文件夾中,那程序名稱(chēng)是App_Code。
??????????????? 這樣在Web站點(diǎn)是添加該類(lèi)庫(kù)的引用后,運(yùn)行每個(gè)頁(yè)面,會(huì)發(fā)現(xiàn)其源文件中都會(huì)加入“<!--這是每個(gè)頁(yè)面都會(huì)動(dòng)態(tài)生成的文字。--grayworm-->”這句話(huà)。同樣的方法你也可以在其中加入JS代碼。
???????2、身份檢查
??????????? 大家在作登錄時(shí),登錄成功后,一般要把用戶(hù)名放在Session中保存,在其它每一個(gè)頁(yè)面的Page_Load事件中都檢查Session中是否存在用戶(hù)名,如果不存在就說(shuō)明用戶(hù)未登錄,就不讓其訪(fǎng)問(wèn)其中的內(nèi)容。
??????????? 在比較大的程序中,這種做法實(shí)在是太笨拙,因?yàn)槟銕缀跻诿恳粋€(gè)頁(yè)面中都加入檢測(cè)Session的代碼,導(dǎo)致難以開(kāi)發(fā)和維護(hù)。下面我們看看如何使用HttpModule來(lái)減少我們的工作量
??????????? 由于在這里我們要用到Session中的內(nèi)容,我們只能在AcquireRequestState和PreRequestHandlerExecute事件中編寫(xiě)代碼,因?yàn)樵贖ttpModule中只有這兩事件中可以訪(fǎng)問(wèn)Session。這里我們選擇PreRequestHandlerExecute事件編寫(xiě)代碼。
????????????第一步:創(chuàng)建一個(gè)類(lèi)庫(kù)ClassLibrary831。
??????????? 第二步:編寫(xiě)一個(gè)類(lèi)實(shí)現(xiàn)IHttpModule接口
????????????????class TestModule:IHttpModule
??????????????? {
??????????????????? public void Dispose()
??????????????????? {
??????????????????? }
??????????????????? public void Init(HttpApplication context)
??????????????????? {
??????????????????? }
??????????????? }?
??????????? 第三步:在Init事件中注冊(cè)PreRequestHandlerExecute事件,并實(shí)現(xiàn)事件處理方法
???????????????class AuthenticModule:IHttpModule
??????????????? {
??????????????????? public void Dispose(){}
??????????????????? public void Init(HttpApplication context)
??????????????????? {
????????????????????????context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
??????????????????? }
????????????????????void context_PreRequestHandlerExecute(object sender, EventArgs e)
??????????????????? {
??????????????????????? HttpApplication ha = (HttpApplication)sender;
??????????????????????? string path = ha.Context.Request.Url.ToString();
??????????????????????? int n = path.ToLower().IndexOf("Login.aspx");?
??????????????????????? if (n == -1) //是否是登錄頁(yè)面,不是登錄頁(yè)面的話(huà)則進(jìn)入{}
??????????????????????? {
??????????????????????????? if (ha.Context.Session["user"] == null) //是否Session中有用戶(hù)名,若是空的話(huà),轉(zhuǎn)向登錄頁(yè)。
??????????????????????????? {
??????????????????????????????? ha.Context.Response.Redirect("Login.aspx?source=" + path);
??????????????????????????? }
??????????????????????? }
??????????????????? }
??????????????? }?
??????????? 第四步:在Login.aspx頁(yè)面的“登錄”按鈕中加入下面代碼
????????????????protected void Button1_Click(object sender, EventArgs e)
??????????????? {
??????????????????? if(true)??? //判斷用戶(hù)名密碼是否正確
??????????????????? {?
??????????????????????? if (Request.QueryString["source"] != null)
??????????????????????? {
??????????????????????????? string s = Request.QueryString["source"].ToLower().ToString();?? //取出從哪個(gè)頁(yè)面轉(zhuǎn)來(lái)的
??????????????????????????? Session["user"] = txtUID.Text;
??????????????????????????? Response.Redirect(s); //轉(zhuǎn)到用戶(hù)想去的頁(yè)面
??????????????????????? }
??????????????????????? else
??????????????????????? {
??????????????????????????? Response.Redirect("main.aspx");??? //默認(rèn)轉(zhuǎn)向main.aspx
??????????????????????? }
??????????????????? }?
??????????????? }?
??????????? 第五步:在Web.Conofig中注冊(cè)一下這個(gè)HttpModule模塊
??????????<httpModules>
?????????? <add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>
????????? </httpModules>?
?????? 3、多模塊的操作?
??????????? 如果定義了多個(gè)HttpModule,在web.config文件中引入自定義HttpModule的順序就決定了多個(gè)自定義HttpModule在處理一個(gè)HTTP請(qǐng)求的接管順序。
?
HttpHandler
??? HttpHandler是HTTP請(qǐng)求的處理中心,真正地對(duì)客戶(hù)端請(qǐng)求的服務(wù)器頁(yè)面做出編譯和執(zhí)行,并將處理過(guò)后的信息附加在HTTP請(qǐng)求信息流中再次返回到HttpModule中。
??? HttpHandler與HttpModule不同,一旦定義了自己的HttpHandler類(lèi),那么它對(duì)系統(tǒng)的HttpHandler的關(guān)系將是“覆蓋”關(guān)系。
??? IHttpHandler接口聲明
????public interface IHttpHandler
??? {
??????? bool IsReusable { get; }
??????? public void ProcessRequest(HttpContext context); //請(qǐng)求處理函數(shù)
??? }
????
??? 示例:把硬盤(pán)上的圖片以流的方式寫(xiě)在頁(yè)面上
????????class TestHandler : IHttpHandler
??????? {
????????????public void ProcessRequest(HttpContext context)
??????????? {
??????????????? FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);
??????????????? byte[] b = new byte[fs.Length];
??????????????? fs.Read(b, 0, (int)fs.Length);
??????????????? fs.Close();
??????????????? context.Response.OutputStream.Write(b, 0, b.Length);
??????????? }
??????????? public bool IsReusable
??????????? {
??????????????? get
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????? }
??????? Web.Config配置文件
??????<httpHandlers>
?????? <add verb="*" path="*" type="ClassLibrary831.TestHandler,ClassLibrary831"></add>
????? </httpHandlers>?
???????????Verb屬性:指定了處理程序支持的HTTP動(dòng)作。*-支持所有的HTTP動(dòng)作;“GET”-支持Get操作;“POST”-支持Post操作;“GET, POST”-支持兩種操作。?
Path屬性:指定了需要調(diào)用處理程序的路徑和文件名(可以包含通配符)。“*”、“*.aspx”、“showImage.aspx”、“test1.aspx,test2.aspx”
Type屬性:用名字空間、類(lèi)名稱(chēng)和程序集名稱(chēng)的組合形式指定處理程序或處理程序工廠的實(shí)際類(lèi)型。ASP.NET運(yùn)行時(shí)首先搜索bin目錄中的DLL,接著在GAC中搜索。?
??????? 這樣程序運(yùn)行的效果是該網(wǎng)站的任何一個(gè)頁(yè)面都會(huì)顯示worm.jpg圖片。如何只讓一個(gè)頁(yè)面(default21.aspx)執(zhí)行HttpHandler中的ProcessRequest方法呢?最簡(jiǎn)單的辦法是在Web.Config文件中把path配置信息設(shè)為default21.aspx。
??????? 根據(jù)這個(gè)例子大家可以考慮一下如何編寫(xiě)“驗(yàn)證碼”了。
IHttpHandler工廠
??? IHttpHandlerFactory的作用是對(duì)IHttpHandler進(jìn)行管理。工廠的作用請(qǐng)見(jiàn)http://hi.baidu.com/grayworm/blog/item/4a832160f8c9de46eaf8f8c1.html"
??? IHttpHandlerFactory接口的聲明:
????????public interface IHttpHandlerFactory
??????? {
??????????? IHttpHandler GetHandler (HttpContext context,string requestType,string url,string pathTranslated);
??????????? void ReleaseHandler (IHttpHandler handler);
??????? }
?????? GetHandler返回實(shí)現(xiàn)IHttpHandler接口的類(lèi)的實(shí)例,ReleaseHandler使工廠可以重用現(xiàn)有的處理程序?qū)嵗?
??? 示例:兩個(gè)用IHttpHandlerFactory來(lái)實(shí)現(xiàn)對(duì)不同HttpHandler的調(diào)用。
??? 有兩個(gè)HttpHandler:將圖片顯示在頁(yè)面上的HttpHandler和生成驗(yàn)證碼的Handler
??????? //將圖片顯示在頁(yè)面上的Handler
????????class TestHandler : IHttpHandler
??????? {
??????????? public void ProcessRequest(HttpContext context)
??????????? {
??????????????? FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);
??????????????? byte[] b = new byte[fs.Length];
??????????????? fs.Read(b, 0, (int)fs.Length);
??????????????? fs.Close();
??????????????? context.Response.OutputStream.Write(b, 0, b.Length);
??????????? }
??????????? public bool IsReusable
??????????? {
??????????????? get
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????? }
??????? //生成驗(yàn)證碼的Handler?
????????class CodeHandler:IHttpHandler
??????? {
??????????? public bool IsReusable
??????????? {
??????????????? get
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????????? public void ProcessRequest(HttpContext context)
??????????? {
??????????????? Image b = new Bitmap(50,20);
??????????????? Graphics g = Graphics.FromImage(b);
??????????????? SolidBrush sb = new SolidBrush(Color.White);
??????????????? Font f = new Font("宋體", 12);
??????????????? string str = "";
??????????????? Random r = new Random();
??????????????? for (int i = 0; i < 4; i++)
??????????????? {
??????????????????? str += r.Next(10);
??????????????? }
??????????????? g.DrawString(str,f,sb,0,0);
??????????????? b.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
??????????? }
??????? }?
???????? IHttpHandler工廠
?????????class TestHandlerFactory : IHttpHandlerFactory
???????? {
??????????? public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
??????????? {
????????????????
??????????????? string fname = url.Substring(url.IndexOf('/') + 1);
??????????????? while (fname.IndexOf('/') != -1)
??????????????????? fname = fname.Substring(fname.IndexOf('/') + 1);
??????????????? string cname = fname.Substring(0, fname.IndexOf('.'));
??????????????? string className ="";
??????????????? className = "ClassLibrary831.CodeHandler";
??????????????? object h = null;
??????????????? try
??????????????? {
??????????????????? //h = new TestHandler();
??????????????????? h = Activator.CreateInstance(Type.GetType(className));
??????????????? }
??????????????? catch (Exception e)
??????????????? {
??????????????????? throw new HttpException("工廠不能為類(lèi)型" + cname + "創(chuàng)建實(shí)例。", e);
??????????????? }
??????????????? return (IHttpHandler)h;
??????????? }
??????????? public void ReleaseHandler(IHttpHandler handler)
??????????? {
??????????? }
???????? }(車(chē)延祿)
??????? 配置文件
??? <httpHandlers>
??? <add verb="*" path="default21.aspx,default22.aspx" type="ClassLibrary831.TestHandlerFactory,ClassLibrary831"></add>
?? </httpHandlers>
?? 這樣TestHandlerFactory就會(huì)根據(jù)請(qǐng)求的不同頁(yè)面執(zhí)行不同的HttpHandler處理程序了。
HttpHandler使用會(huì)話(huà)
??? 如果要在處理程序中使用Session,那必須把該HttpHandler實(shí)現(xiàn)IRequiresSessionState接口,,IRequiresSessionState接口是個(gè)空接口,它沒(méi)有抽象方法,只是一個(gè)標(biāo)記。此處就不作例子驗(yàn)證了
?
?
| ASP.Net處理Http Request時(shí),使用Pipeline(管道)方式,由各個(gè)HttpModule對(duì)請(qǐng)求進(jìn)行處理,然后到達(dá) HttpHandler,HttpHandler處理完之后,仍經(jīng)過(guò)Pipeline中各個(gè)HttpModule的處理,最后將HTML發(fā)送到客戶(hù)端瀏覽 器中。 生命周期中涉及到幾個(gè)非常重要的對(duì)象:HttpHandler,HttpModule,IHttpHandlerFactory,他們的執(zhí)行(順序)大致的執(zhí)行過(guò)程是這樣的:client端發(fā)送頁(yè)面請(qǐng)求,被IIS的某個(gè)進(jìn)程截獲,它根據(jù)申請(qǐng)的頁(yè) 面后綴(.aspx)不同,調(diào)用不同的頁(yè)面處理程序(.asp->asp.dll; .aspx->ISAPI.dll).而頁(yè)面處理程序在處理過(guò)程中,則要經(jīng)歷HttpModule,HttpHandler的處理:前者HttpModule用于頁(yè)面處理前和處理后的一些事件的處理,后者HttpHandler進(jìn)行真正的頁(yè)面的處理。
? ? ASP.Net系統(tǒng)本身配置有很多HttpHandler和HttpModule,以處理aspx等.Net標(biāo)準(zhǔn)的頁(yè)面文件,以及這些頁(yè)面文件中標(biāo) 準(zhǔn)的事件處理等。查看%System%/Microsoft.NET\Framework\v2.0.50727\CONFIG目錄下的 web.config文件中的httpHandlers和httpModules節(jié)點(diǎn),可以看到這些配置。如果有興趣,可以使用Reflector查 看.Net系統(tǒng)中相關(guān)的類(lèi)和方法,了解.Net如何處理以及做了什么處理。 .Net也提供了一套機(jī)制來(lái)開(kāi)發(fā)自定義的HttpHandler和 HttpModule,均可以用于對(duì)HttpRequest的截取,完成自定義的處理。 HttpModule 繼承System.Web.IHttpModule接口,實(shí)現(xiàn)自己的HttpModule類(lèi)。必須要實(shí)現(xiàn)接口的兩個(gè)方法:Init和Dispose。在 Init中,可以添加需要截取的事件;Dispose用于資源的釋放,如果在Init中創(chuàng)建了自己的資源對(duì)象,請(qǐng)?jiān)贒ispose中進(jìn)行釋放。 namespace MyModule ???? ? public void Dispose() private void BeginRequest(object r_objSender, EventArgs r_objEventArgs)
將編譯的dll文件拷貝到web項(xiàng)目的bin目錄下,在web項(xiàng)目的web.config文件system.web節(jié)點(diǎn)中配置:? ?? ?? <httpModules> ? ? ? HttpHandler是完全的對(duì)Http Request的截取。 MyHttpHandler, MyHandler"/> ??? verb屬性配置這個(gè)HttpHandler處理那些HTTP方法,例如GET、POST等,如果是處理所有方法,就用*。path屬性配置HttpHandler對(duì)哪些文件進(jìn)行處理,例如可以是myfile.cc,如果是處理所有的.cc文件,就用*.cc。 ??? 對(duì)HttpHandler的使用,比較典型的有.Net的Web MVC開(kāi)源項(xiàng)目Maverick。Maverick使用一個(gè)Dispatcher類(lèi)對(duì)所有的Http Request進(jìn)行截取,他以.m作為后綴名向Web服務(wù)器提交請(qǐng)求,在Dispatcher中,將.m的后綴去掉,提取Command Name,然后以這個(gè)command name從配置文件中加載處理的flow,形成一個(gè)chain,依次對(duì)chain上的各個(gè)command和view進(jìn)行處理,對(duì)各個(gè)command和 view的處理結(jié)果可能會(huì)在chain中選擇不同的處理分支,每個(gè)處理的Step中將處理結(jié)果的HTML寫(xiě)入Response的緩存中進(jìn)行輸出。 ??? 總之,將HttpModule、HttpHandler,以及使用Ajax等將客戶(hù)端進(jìn)行封裝結(jié)合起來(lái),能夠給web項(xiàng)目的開(kāi)發(fā)帶來(lái)非常大的改善空間。 Asp.Net HttpHandler實(shí)現(xiàn)URL重寫(xiě)的 |
轉(zhuǎn)載于:https://www.cnblogs.com/cmblogs/p/4028621.html
總結(jié)
以上是生活随笔為你收集整理的httpModules 与 httpHandlers的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ORACLE 数据库安装后,PL/SQL
- 下一篇: 多比Web 3D展示(3D机房/3D监控