ASP.NT运行原理和页面生命周期详解及其应用
1. 下面是我画的一张关于asp.net运行原理和页面生命周期的一张详解图。如果你对具体不太了解,请参照博客园其他帖子。在这里我主要讲解它的实际应用。
(一) HttpModule工作原理
当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。
第一步:新建类库MyHttpModule,实现接口IHttpModule。(如果是类库文件要先引用system.web命名空间)
第二步:在Init方法中可以实现module中的19个标准事件。现在我们只举其中的一个BeginRequest事件。在此事件中对请求进行截断。其他事件的使用请参照博客园其他博文。如图:
第四步:在webconfig文件的httpmodule节点下做如下配置。此节点位于system.web节点下。
第五步:任意请求一个动态页面,结果如下图所示:
再次请求一个页面:
我们看到我们请求了不同的页面,但都对内容进行了截取。
1 public class MyHttpModule:IHttpModule 2 3 { 4 5 public void Dispose() 6 7 { 8 9 throw new NotImplementedException(); 10 11 } 12 13 public void Init(HttpApplication application) 14 15 { 16 17 application.BeginRequest += new EventHandler(application_BeginRequest); 18 19 application.EndRequest += new EventHandler(application_EndRequest); 20 21 application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute); 22 23 application.PostRequestHandlerExecute += new EventHandler(application_PostRequestHandlerExecute); 24 25 application.ReleaseRequestState += new EventHandler(application_ReleaseRequestState); 26 27 application.AcquireRequestState += new EventHandler(application_AcquireRequestState); 28 29 application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest); 30 31 application.AuthorizeRequest += new EventHandler(application_AuthorizeRequest); 32 33 application.ResolveRequestCache += new EventHandler(application_ResolveRequestCache); 34 35 application.PreSendRequestHeaders += new EventHandler(application_PreSendRequestHeaders); 36 37 application.PreSendRequestContent += new EventHandler(application_PreSendRequestContent); 38 39 } 40 41 void application_PreSendRequestContent(object sender, EventArgs e) 42 { 43 44 HttpApplication application = (HttpApplication)sender; 45 application.Context.Response.Write("application_PreSendRequestContent<br/>"); 46 47 } 48 void application_PreSendRequestHeaders(object sender, EventArgs e) 49 50 { 51 52 HttpApplication application = (HttpApplication)sender; 53 54 application.Context.Response.Write("application_PreSendRequestHeaders<br/>"); 55 56 } 57 58 void application_ResolveRequestCache(object sender, EventArgs e) 59 60 { 61 62 HttpApplication application = (HttpApplication)sender; 63 64 application.Context.Response.Write("application_ResolveRequestCache<br/>"); 65 66 } 67 68 void application_AuthorizeRequest(object sender, EventArgs e) 69 70 { 71 72 HttpApplication application = (HttpApplication)sender; 73 74 application.Context.Response.Write("application_AuthorizeRequest<br/>"); 75 76 } 77 78 void application_AuthenticateRequest(object sender, EventArgs e) 79 80 { 81 82 HttpApplication application = (HttpApplication)sender; 83 84 application.Context.Response.Write("application_AuthenticateRequest<br/>"); 85 86 } 87 88 void application_AcquireRequestState(object sender, EventArgs e) 89 90 { 91 92 HttpApplication application = (HttpApplication)sender; 93 94 application.Context.Response.Write("application_AcquireRequestState<br/>"); 95 96 } 97 98 void application_ReleaseRequestState(object sender, EventArgs e) 99 100 { 101 102 HttpApplication application = (HttpApplication)sender; 103 104 application.Context.Response.Write("application_ReleaseRequestState<br/>"); 105 106 } 107 108 void application_PostRequestHandlerExecute(object sender, EventArgs e) 109 110 { 111 112 HttpApplication application = (HttpApplication)sender; 113 114 application.Context.Response.Write("application_PostRequestHandlerExecute<br/>"); 115 116 } 117 118 void application_PreRequestHandlerExecute(object sender, EventArgs e) 119 120 { 121 122 HttpApplication application = (HttpApplication)sender; 123 124 application.Context.Response.Write("application_PreRequestHandlerExecute<br/>"); 125 126 } 127 128 void application_EndRequest(object sender, EventArgs e) 129 { 130 131 HttpApplication application = (HttpApplication)sender; 132 133 application.Context.Response.Write("application_EndRequest<br/>"); 134 135 } 136 137 void application_BeginRequest(object sender, EventArgs e) 138 139 { 140 141 HttpApplication application = (HttpApplication)sender; 142 143 application.Context.Response.Write("application_BeginRequest<br/>"); 144 145 } 146 147 }
第六步:我们再来看看asp.net管道事件中的其它一些事件。以及他们的执行顺序。
结果如图:
第七步:其实我们还可以在global文件中处理httpmodule管道的事件。在此不再举例说明。因为当请求到达httpapplication中开始beginrequest事件时,事件已经流到了global文件中。
(二) HttpHandler工作原理
1) 概述
HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
2) IHttpHandlerd定义
IHttpHandler定义了如果要实现一个HTTP请求的处理所必需实现的一些系统约定。HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。
3) IHttpHandlerd如何处理HTTP请求
当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。
对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。所谓一个HttpHandlerFactory,所谓一个HttpHandlerFactory,是指当一个HTTP请求到达这个HttpHandler Factory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。
一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。
下面我举一个利用httphandler进行全局防盗链处理的实例。
第一步:新建类库ImgProcess,实现接口IHttpHandler。(注意如果是类库中要添加system.web的引用)。在httphandler的pr方法中我们可以获得请求的图片地址和请求的来源。如果请求的图片路径不存在或者请求的来源不是本站,则输出默认的图片流。(需要配置IIS,因为IIS默认是直接返回静态文件的)
实例如下:
1 public void ProcessRequest(HttpContext context) 2 3 { 4 5 //如果想要让对图片的请求经过framework,则需要配置IIS,因为默认的图片是IIS处理的。 6 7 context.Response.ContentType = "text/plain"; 8 9 string fileImagPath = context.Server.MapPath(context.Request.FilePath); 10 11 Uri referrerUrl = context.Request.UrlReferrer; 12 13 Image bookImg = null; 14 15 //当是从本网站请求过来的,并且此图片存在的话 16 17 if (referrerUrl != null && referrerUrl.ToString().IndexOf("localhost:9090") > 0) 18 19 { 20 21 if (File.Exists(fileImagPath)) 22 23 { 24 25 bookImg = Bitmap.FromFile(fileImagPath); 26 27 28 29 //可以在这里给图片加水印等处理 30 31 //todo 32 33 } 34 35 else 36 37 { 38 39 bookImg = Bitmap.FromFile(context.Server.MapPath("~/Images/BookImages/noImg.jpg")); 40 41 } 42 43 44 45 } 46 47 else 48 49 { 50 51 bookImg = Bitmap.FromFile(context.Server.MapPath("~/Images/BookImages/default.jpg")); 52 53 } 54 55 context.Response.ContentType = "image/jpeg"; 56 57 //将图片存入输出流 58 59 bookImg.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); bookImg.Dispose(); 60 61 context.Response.End(); 62 63 } 64 65
第二步:配置webconfig文件下的httpHandlers节点。
<httpHandlers>
<!--全¨?局?一°?般ã?处ä|理¤¨ª程¨¬序¨°的Ì?配?置?-->
<add verb="*" path="/Images/BookImages/*.jpg" type="BookShop.Web.CommonHelper.ImgProcess"/>
</httpHandlers>
Verb表示请求方式 GET/POST 可以用*表示所有方式
Path 请求时,要转到全局一般处理程序的文件名 可以使用通配符
Type 把请求转给哪一个一般处理程序去处理,这里写类名.如果是WebSite,那么就写类名就行了.如果是Web应用程序,就写 命名空间.类名
第三步:运行如下:
正常情况下:
直接请求图片地址的话:
第四步:还可以在aspx.cs文件中重载页面生命周期中的委托方法。
public partial class WebForm5 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected override void InitializeCulture() { base.InitializeCulture(); } }
大概就这样了,如有不详或者错误的地方欢迎指正。