ASP.Net请求处理机制初步探索之旅 - Part 2 核心

   可以先看:http://www.cnblogs.com/kissdodog/p/3527871.html

   上一篇我们了解了一个请求从客户端发出到服务端接收并转到ASP.Net处理入口的过程,这篇我们开始探索ASP.Net的核心处理部分,借助强大的反编译工具,我们会看到几个熟悉又陌生的名词(类):HttpWorkerRequest、HttpRuntime、HttpContext、HttpApplication等。

一、第一个入口:ISAPIRuntme.ProcessRequest()

   ISAPIRuntime是进入NET托管环境的入口,在其PR方法中通过一个ecb句柄指向了当前请求报文体的内存地址,将HTTP请求报文简单封装为一个

ISAPIWorkerRequest对象(此类继承于HttpWorkerRequest对象),然后就是调用其PR(ProcessRequest)方法。

     Asp.Net中准备用于处理的请求都必须封装为HttpWorkerRequest类型的对象,HttpWorkerRequest是一个抽象类型.

二、第二个入口:HttpRuntime.ProcessRequest()

    当请求进入HttpRuntime,由它来决定如何处理请求。默认情况下在machine.config和Web.config中并没有显式定义httpRuntime节点,但该节点是有默认值的。通常情况下,我们可以在Web.config中更改httpRuntime节点的默认值。

    此PR方法主要将上一步的HttpWorkerRequest对象封装成HttpContext对象这是一个重要的Http上下文对象,两个重要类型的字段也随之被初始化:HttpRequest对象和HttpResponse对象。我们通过HttpContext.Current获取到这个实例且该实例会在整个生命周期中存活,通过它还可以获取到一些常用对象,如Request,Response,Session 等。

   接下来通过httpcontext对象获取一个IHttpHandler类型的对象,此对象本质是HttpApplication类型(通过msdn可以看到httpapplication实现了IHttphandler接口,即整个web是一个大的处理程序,其中aspx,ashx等是具体的处理程序,它们也实现了IHttphandler接口)HttpApplication其实就是web应用程序的实例。在其处理完请求后会进入到应用程序池中而不是立即销毁跟ADO.net连接池一个道理。通过反射的方式可以看出是将Global文件所编译后的类封装出来一个HttpApplication实例。

 

    (重点)现在HttpApplication需要进行初始化请求处理管道(管道由托管模块和处理程序(Handlers)组成)来分别处理ASP.Net WebForm或ASP.Net MVC等类型的页面的响应操作。

   a)通过读取Web.config配置文件中关于HttpModule的信息,然后将其传递给HttpModule的集合,遍历集合分别对其每一个HttpModule执行其对应的Init方法。主要目的是将httpapplication对象传递给各个module

   b)HttpModule第一时间完成针对HttpApplication对象19个管道事件注册

   c)调用HttpModule中各个事件对应的执行方法

   可参看:http://www.cnblogs.com/kissdodog/p/3527922.html 中第四块。 

关于请求处理管道:

  HttpApplication 利用.Net中的事件机制,将请求的处理过程分成多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以自定义每一个请求的扩展处理过程。对于 HttpApplication 来说,到 ASP.NET 4.0 版本,提供了19 个标准事件,如下图所示:

ASP.Net请求处理机制初步探索之旅 - Part 2 核心_第1张图片

 Asp.net服务器对于每一次请求的处理过程都相同,都要经过这个HttpApplication处理管道。管道内部的处理过程是固定的。

  1、最先触发的事件是BeginRequest,这个事件标志着Asp.net服务器处理工作得开始,也是程序员在Asp.net中针对请求所能够处理的第一个事件。

  2、开始处理请求后,第一个重要工作就是确定请求用户的身份以实现安全机制,这个工作通过AuthenticateRequest和PostAuthenticateRequest两个事件提供检查当前请求用户身份的机会。检查后的用户可以通过HttpContext的User属性获取到。如:

    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string UserName = HttpContext.Current.User.Identity.Name;
    }

  3、获取用户身份之后,将开始检查权限的工作。如果没有通过安全检查,一般情况下,都跳过剩下的事件,直接出发EndRequest事件,结束请求的处理过程。

  4、当用户通过了权限检查,为了最快获得结果,Asp.net将进行缓存检查,看看是否可以从以前的缓存中直接取得处理的结果。

   5、当不能从缓存中获取结果的时候,必须通过一次处理来计算出当前请求的结果。在Asp.net中,用于 处理请求以得到结果的对象称为处理程序Handler,在Asp.net中提供了许多的处理程序,程序员也 可以自定义处理程序。为了处理这个请求,Asp.net必须按照匹配规则找到一个处理当前请求的处理 程序,PostMapRequestHandler事件表示Asp.net已经获取了这个处理程序,HttpContext的Handler 属性就表示这个处理程序对象。从上面的分析可以看到,HttpContext的Handler属性到这里才有实 际的意义。

  6、虽然有了处理程序对象,但是还不能立即开始处理,因为会话状态还未获取,还需要先获取Session然后才能获取事件处理程序。
PreRequestHandlerExecute通知程序员,马上开始调用处理程序了,有什么没有准备好的赶紧准备。
  7、调用处理程序。
  8、在处理程序完成之后,服务器开始进行扫尾工作,PostRequestHandlerExecute事件通知程序员,Asp.net服务器的处理程序已经完成。在处理完成之后,由于在处理程序中,用户可能修改了用户特定的专属数据,那么修改之后的用户状态数据可能需要进行序列化或者进行保存处理。ReleaseRequestState事件通知程序员需要释放这些状态数据,PostReleaseRequestState则表示已经释放完成。
  9、在处理完成之后,如果希望将这次处理的结果缓存起来,以便在后继的请求中可以直接使用这个结果,UpdateRequestCache事件提供了处理的机会,PostUpdateRequestCache则表示缓存已经更新完成。
  10、在Asp.net 4.0之后,新增加了两个时间完成处理的日志工作:LogRequest表示将这次请求记入日志中,PostLogRequest表示完成了日志工作。
EndRequest是所有请求都要经过的最后一个HttpApplication处理管道的事件,也是程序员处理Asp.net处理请求中的最后一个机会。这个事件之后,处理的结果将被回应道浏览器,完成Asp.net服务器的处理工作。

 

至于在请求处理管道中的细节,我们在Part 3中再看,今天就到此为止,谢谢!

 

你可能感兴趣的:(ASP.Net请求处理机制初步探索之旅 - Part 2 核心)