深圳升蓝软件
数据库开发 .Net技术  |  ASP技术 PHP技术 JSP技术 应用技术类   
Hiblue Software

ASP.NET Framework深度历险(3)


March 25,2004
Author:uestc95
ArticleType:原创
E-mail:[email protected]
.NET Framework Version:1.0.3705正式版
VS.NET(C#) Version:7.0.9466正式版



    这几天胃口还算好,虽然算不上“吃嘛嘛香”,但是也算是不错了,但愿能增上几斤才好。
    怎么样,我们在Chapter Two最后提出的两个问题估计早出来了吧,:)
    First:为什么在HttpModule中不能使用Session?
    Second:系统默认的几个HttpModule在哪里配置的?

    我们先挑软柿子捏,第二个问题的答案是:在文件machine.config中配置,比如在你的系统文件目录中的C:WI

NNTMicrosoft.NETFrameworkv1.0.3705CONFIGmachine.config。
    虽然是个软柿子,但是还是有些东东在里面的,那就是machine.config和我们常见的web.config有什么关

系呢?在ASP.NET Framework启动处理一个Http Request的时候,她会依次加载machine.config以及你请求页面

所在目录的web.config文件,里面的配置是有<remove>标签的,什么意思不说也知道了吧。如果你在machine.c

onfig中配置了一个自己的HttpModule,你仍然可以在离你最近web.config文件中“remove”掉这个映射关系。
    至于第一个问题,呵呵,如果你仔细的运行过上次的文件但是没有自己仔细深入研究一下的话,一定会觉

得在HttpModule中的确无法使用Session,:)。如果你发现上次提出的问题本身就是一个"Problem",那么恭喜你,你没有掉进我故意给出的框框中,并且很有质疑精神,:)
    今天我们就来解释一下HttpModule和HttpHandler之间的关系,在今天的“日记”完成的时候,你也就会发现第一个问题的答案了。

    Chapter Three -- 深入HttpModule

    我们曾经提及当一个Http Request被ASP.NET Framework捕获之后会依次交给HttpModule以及HttpHandler来处理,但是不能理解为HttpModule和HttpHandler是完全独立的,实际上是,在Http Request在HttpModule传递的过程中会在某个事件内将控制权交给HttpHandler的,而真正的处理在HttpHandler中完成之后,再将控制权交还给HttpModule。也就是说HttpModule在某个请求经过她的时候会再恰当时候同HttpHandler进行通信,在何时,如何通信呢?这就是下面提到的了。
    我们提到在HttpModule中最开始的事件是BeginRequest,最终的事件是EndRequest。你如果仔细看上次给出的源程序的话,应当发现在方法Init()中参数我们传递的是一个HttpApplication类型,而我们曾经提及的两个事件正是这个传递进来的HttpApplication的事件之一。
    HttpApplication还有其它的事件,分别如下:
            application.BeginRequest
            application.EndRequest
            application.PreRequestHandlerExecute
            application.PostRequestHandlerExecute
            application.ReleaseRequestState
            application.AcquireRequestState
            application.AuthenticateRequest
            application.AuthorizeRequest
            application.ResolveRequestCache
            application.PreSendRequestHeaders
            application.PreSendRequestContent

      需要注意的是,在事件EndRequest之后还会继续执行application.PreSendRequestHeaders以及application.PreSendRequestContent事件,而这两个事件大家想必应当从名称上面看得出来事做什么用途的了吧。是的,一旦触发了这两个事件,就表明整个Http Request的处理已经完成了,在这两个事件中是开始向客户端传送处理完成的数据流了。看到这里,您应当有一个疑问才对:怎么没见到HttpHandler就处理完成了?不是提到过HttpHandler才是真正处理Http Request的吗?如果你有这个疑问表明你是仔细在看,也不枉我打字打得这莫累,:)。
    其实一开始我就提到了,在一个http request在HttpModule传递过程中,会在某一个时刻(确切的说应当是事件)中将这个请求传递给HttpHandler的。这个事件就是ResolveRequestCache,在这个事件之后,HttpModule会建立一个HttpHandler的入口实例(做好准备了,:)),但是此时并没有将控制权交出,而是继续触发AcquireRequestState以及PreRequestHandlerExecute事件(如果你实现了的话)。看到了吗,最后一个事件的前缀是Pre,呵呵。这表明下一步就要进入HttpHandler了,的确如此,正如我们猜想的那样,在PreRequestHandlerExecute事件之后,HttpModule就会将控制权暂时交给HttpHandler,以便进行真正的http request处理工作。而在HttpHandler内部会执行ProcessRequest来处理请求。在HttpHandler处理完毕之后,会将控制权交还给HttpModule,HttpModule便会继续对处理完毕的http Request进行层层的转交动作,直到返回到客户端。
   怎么样,是不是有些混乱?呵呵,苦于纯文本无法画流程图,我手头上已经画好了一个整个HttpModule的生命周期图,我只能暂且在这里用字符描绘一下前后流程了,如果你想要这个图片,可以给我发送mail,我给你mail过去。
   Http Request在整个HttpModule中的生命周期图:

                    Http Request开始
                        |
                       HttpModule
                            |
                     HttpModule.BeginRequest()
                        |
                HttpModule.AuthenticateRequest()
                        |
                      HttpModule.AuthorizeRequest()
                        |
                  HttpModule.ResolveRequestCache()
                        |
                    建立HttpHandler控制点
                        |
                接着处理(HttpHandler已经建立,此后Session可用)
                        |
                  HttpModule.AcquireRequestState()
                        |
                HttpModule.PreRequestHandlerExecute()
                        |
                   进入HttpHandler处理HttpRequest
                        |
                    HttpHandler.ProcessRequest()
                        |
            返回到HttpModule接着处理(HttpHandler生命周期结束,Session失效)
                        |
                HttpModule.PostRequestHandlerExecute()
                        |
                HttpModule.ReleaseRequestState()
                        |
                HttpModule.UpdateRequestCache()
                        |
                    HttpModule.EndRequest()
                        |
                HttpModule.PreSendRequestHeaders()
                        |
                HttpModule.PreSendRequestContent()
                        |
                    将处理后的数据返回客户端
                        |
                         整个Http Request处理结束
   
   
     怎么样,从上面的图中应当找到上次我们提出的第一个问题的答案了吧。
     为了验证上面的流程,我们可以用下面的这个自己的HttpModuel来验证一下就知道了。
     注意我们下面给出的是类的内容,框架还是前次我们给出的那个,自己加上就好了:

        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
            application.EndRequest += (new EventHandler(this.Application_EndRequest));
            application.PreRequestHandlerExecute +=(new EventHandler(this.Application_PreRequestHandlerExecute));
            application.PostRequestHandlerExecute  +=(new EventHandler(this.Application_PostRequestHandlerExecute));
            application.ReleaseRequestState  +=(new EventHandler(this.Application_ReleaseRequestState));
            application.AcquireRequestState +=(new EventHandler(this.Application_AcquireRequestState));
            application.AuthenticateRequest +=(new EventHandler(this.Application_AuthenticateRequest));
            application.AuthorizeRequest +=(new EventHandler(this.Application_AuthorizeRequest));
            application.ResolveRequestCache +=(new EventHandler(this.Application_ResolveRequestCache));
            application.PreSendRequestHeaders +=(new EventHandler(this.Application_PreSendRequestHeaders));
            application.PreSendRequestContent +=(new EventHandler(this.Application_PreSendRequestContent));
        }
   
        private void Application_PreRequestHandlerExecute(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_PreRequestHandlerExecute<br>");
        }

        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_BeginRequest<br>");
        }
   
        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_EndRequest<br>");

        }        
   
        private void Application_PostRequestHandlerExecute(Object source,EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_PostRequestHandlerExecute<br>");

        }

        private void Application_ReleaseRequestState(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_ReleaseRequestState<br>");

        }

        private void Application_UpdateRequestCache(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_UpdateRequestCache<br>");

        }

        private void Application_AuthenticateRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_AuthenticateRequest<br>");

        }

        private void Application_AuthorizeRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_AuthorizeRequest<br>");

        }

        private void Application_ResolveRequestCache(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_ResolveRequestCache<br>");

        }

        private void Application_AcquireRequestState(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_AcquireRequestState<br>");

        }

        private void Application_PreSendRequestHeaders(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_PreSendRequestHeaders<br>");

        }

        private void Application_PreSendRequestContent(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            context.Response.Write("Application_PreSendRequestContent<br>");

        }
        public void Dispose()
        {
        }


       好了,手累的不行了,:)
       老规矩,下面的问题仔细考虑:
       HttpModule中的Application的多个事件和Global.asax中的Application事件有联系吗?如果有,该会有哪些联系呢?

       下回会探讨HttpHandler的构建了,:)
       不过最近挺忙,不知道何时能继续......尽力吧。
       See you later.

       (待续,欢迎探讨:[email protected])
Copyright © 2001-2008 Shenzhen Hiblue Software Team All rights reserved