ASP.NET的运行原理-请求处理管道总结
一、Asp.Net Web Form管道
请求进入Asp.Net工作进程后,由进程创建HttpWorkRequest对象,封装此次请求有关的所有信息,然后进入HttpRuntime类进行进一步处理。HttpRuntime通过请求信息创建HttpContext上下文对象,此对象将贯穿整个管道,直到响应结束。同时创建或从应用程序池里初始化一个HttpApplication对象,由此对象开始处理之前注册的多个HttpModule。之后调用HandlerFactory创建Handler处理程序,最终处理此次请求内容,生成响应返回。
二、Asp.net HttpModule
用处:
1、权限认证和授权:每个请求都经过Module,所以做权限认证很好
2、URL 转发
3、发爬虫
ASP.NET 请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET 把http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给客户端。我们可以在每个HttpModule中都可以干预请求的处理过程。
注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。
HttpModule生命周期示意图
三、Asp.net HttpHandler
HttpHandler是asp.net真正处理Http请求的地方。在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
当一个HTTP请求经过HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。
对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。所谓一个HttpHandlerFactory,是指当一个HTTP请求到达这个HttpHandlerFactory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。
一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。
可以在一个.ashx文件中实现IHttpHandler
这个processrequest
aspx页面:page_load一系列方法
MVC:去匹配控制器、方法
一般处理程序:程序员直接实现代码
一系列处理 到httpruntime 然后创建 httpcontext 并且对象池获取 Application
然后进入管道piplines
7/8事件之间 获取 httpHandler
HttpApplication的处理管道19个事件。
https://www.cnblogs.com/wolf-sun/p/5236185.html
HttpApplication对象是由Asp.net帮助我们创建的,它是asp.net中处理请求的重要对象。为了便于扩展,HttpApplication采用处理管道的方式进行处理,将处理的步骤分为多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以定义一个请求的扩展过程。
对于HttpApplication,到ASP.NET 4.0,提供了19个标准事件。
1.BeginRequest:asp.net开始处理请求的第一个事件,表示处理的开始。
2.AuthenticateRequest:验证请求,一般用来取得请求的用户信息。
3.PostAuthenticateRequest:已经获取请求的用户信息。
4.AuthorizeRequest:授权,一般用来检查用户的请求是否获得权限。
5.PostAuthorizeRequest:用户请求已经获得授权。
6.ResolveRequestCache:获取以前处理缓存的处理结果,如果以前缓存过,那么,不用再进行请求的处理工作,直接返回缓存的结果。
7.PostResolveRequestCache:已经完成缓存的处理工作。
8.PostMapRequestHandler:已经根据用户的请求,创建了请求的处理器对象。
9.AcquireRequestState:取得请求的状态,一般用于session
10.PostAcquireRequestState:已经获得了session
11.PreRequestHandlerExecute:准备执行处理程序。
12.PostRequestHandlerExecute:已经执行了处理程序
13.ReleaseRequestState:释放请求的状态。
14.PostReleaseRequestState:已经释放了请求的状态。
15.UpdateRequestCache:更新缓存。
16.PostUpdateRequestCache:已经更新了缓存。
17.LogRequest:请求的日志操作
18.PostLogRequest:已经完成请求的日志操作。
19.EndRequest:本次请求处理完成。
Global.asax文件与 HttpModule
在asp.net中,Glabal不仅可以注册应用程序和Session事件,还可以注册Http Module暴露出的事件;不仅可以注册系统Module的事件,也可以注册我们自己义的Module暴露出的事件。在具体介绍之前,这里需要首先注意两点:
- 在每处理一个Http请求时,应用程序事件都会触发一遍,但是Application_Start和 Application_End 例外,它仅在第一个资源文件被访问时被触发。
- Http Module无法注册和响应Session事件,对于Session_Start 和 Session_End,只能通过Glabal.asax来处理。
例子:
MyModule.cs文件
public class MyModule:IHttpModule { public event EventHandler ExposedEvent;//HttpModule事件,供Global.asax来订阅 public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest);//订阅HttpApplication的事件 } void context_BeginRequest(object sender, EventArgs e) { HttpContext.Current.Response.Write("BeginRequest"); OnExposedEvent(new EventArgs());//触发HttpModule自定义事件 } protected void OnExposedEvent(EventArgs e) { if (ExposedEvent != null) { ExposedEvent(this, e); } } public void Dispose() { } }
Global.asax文件
void MyModule_ExposedEvent(object sender, EventArgs e) { Response.Write("xixi"); }
3.global.asax中的事件
global.asax中的所有事件可以分成两种,一种是满足特定事件时才会被触发,一种是每次请求都会被按照顺序执行的事件。
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { //不是每次请求都调用 //在Web应用程序的生命周期里就执行一次 //在应用程序第一次启动和应用程序域创建事被调用 //适合处理应用程序范围的初始化代码 } void Application_End(object sender, EventArgs e) { //不是每次请求都调用 //在应用程序关闭时运行的代码,在最后一个HttpApplication销毁之后执行 //比如IIS重启,文件更新,进程回收导致应用程序转换到另一个应用程序域 } void Session_Start(object sender, EventArgs e) { //不是每次请求都调用 //会话开始时执行 } void Session_End(object sender, EventArgs e) { //不是每次请求都调用 //会话结束或过期时执行 //不管在代码中显式的清空Session或者Session超时自动过期,此方法都将被调用 } void Application_Init(object sender, EventArgs e) { //不是每次请求都调用 //在每一个HttpApplication实例初始化的时候执行 } void Application_Disposed(object sender, EventArgs e) { //不是每次请求都调用 //在应用程序被关闭一段时间之后,在.net垃圾回收器准备回收它占用的内存的时候被调用。 //在每一个HttpApplication实例被销毁之前执行 } void Application_Error(object sender, EventArgs e) { //不是每次请求都调用 //所有没有处理的错误都会导致这个方法的执行 } /*********************************************************************/ //每次请求都会按照顺序执行以下事件 /*********************************************************************/ void Application_BeginRequest(object sender, EventArgs e) { //每次请求时第一个出发的事件,这个方法第一个执行 } void Application_AuthenticateRequest(object sender, EventArgs e) { //在执行验证前发生,这是创建验证逻辑的起点 } void Application_AuthorizeRequest(object sender, EventArgs e) { //当安全模块已经验证了当前用户的授权时执行 } void Application_ResolveRequestCache(object sender, EventArgs e) { //当ASP.NET完成授权事件以使缓存模块从缓存中为请求提供服务时发生,从而跳过处理程序(页面或者是WebService)的执行。 //这样做可以改善网站的性能,这个事件还可以用来判断正文是不是从Cache中得到的。 } //------------------------------------------------------------------------ //在这个时候,请求将被转交给合适程序。例如:web窗体将被编译并完成实例化 //------------------------------------------------------------------------ void Application_AcquireRequestState(object sender, EventArgs e) { //读取了Session所需的特定信息并且在把这些信息填充到Session之前执行 } void Application_PreRequestHandlerExecute(object sender, EventArgs e) { //在合适的处理程序执行请求前调用 //这个时候,Session就可以用了 } //------------------------------------------------- //在这个时候,页面代码将会被执行,页面呈现为HTML //------------------------------------------------- void Application_PostRequestHandlerExecute(object sender, EventArgs e) { //当处理程序完成对请求的处理后被调用。 } void Application_ReleaseRequestState(object sender, EventArgs e) { //释放请求状态 } void Application_UpdateRequestCache(object sender, EventArgs e) { //为了后续的请求,更新响应缓存时被调用 } void Application_EndRequest(object sender, EventArgs e) { //EndRequest是在响应Request时最后一个触发的事件 //但在对象被释放或者从新建立以前,适合在这个时候清理代码 } void Application_PreSendRequestHeaders(object sender, EventArgs e) { //向客户端发送Http标头之前被调用 } void Application_PreSendRequestContent(object sender, EventArgs e) { //向客户端发送Http正文之前被调用 } }
托管和非托管是什么意思?
托管代码 (managed code) : 由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
非托管代码 (Unmanaged Code) : 在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。
鸣谢:
https://www.cnblogs.com/lgxlsm/p/5573088.html
https://www.cnblogs.com/fsjohnhuang/archive/2012/02/06/2339647.html
https://blog.csdn.net/weixin_44763552/article/details/121934482
https://www.cnblogs.com/taotaozhuanyong/p/11600770.html