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暴露出的事件。在具体介绍之前,这里需要首先注意两点:

  1. 在每处理一个Http请求时,应用程序事件都会触发一遍,但是Application_Start和 Application_End 例外,它仅在第一个资源文件被访问时被触发。
  2. 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正文之前被调用
        }
    }
View Code

 

托管和非托管是什么意思?

托管代码 (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

posted @ 2014-10-28 23:41  xiaoshi657  阅读(2590)  评论(0编辑  收藏  举报