HttpApplication的認識與加深理解

作者: FengLang  來源: 博客園  發布時間: 2009-10-22 10:13  閱讀: 2938 次  推薦: 1   原文鏈接   [收藏]  

  HttpApplication對象是經由HttpApplicationFactory.GetApplicationInstance(并最終調用HttpRuntime.CreateNonPublicInstance)創建的HttpApplicationFactory它的主要任務是使用 URL 信息來查找 URL 虛擬目錄和匯集的 HttpApplication 對象之間的匹配關系。

  這個工廠類的行為概括為有以下幾點

  1、工廠類維護, HttpApplication 對象池并使用它們來處理應用程序的請求。池的壽命與應用程序的壽命相同。

  2、應用程序的第一個請求到達時,工廠類提取有關應用程序類型的信息(global.asax 類)、設置用于監視更改的文件、創建應用程序狀態并觸發 Application_OnStart 事件。工廠類從池中獲取一個 HttpApplication 實例,并將要處理的請求放入實例中。如果沒有可用的對象,則創建一個新的 HttpApplication 對象。要創建 HttpApplication 對象,需要先完成 global.asax 應用程序文件的編譯。

  3、HttpApplication 開始處理請求,并且只能在完成這個請求后才能處理新的請求。如果收到來自同一資源的新請求,則由池中的其他對象來處理。

  4、應用程序對象允許所有注冊的 HTTP 模塊對請求進行預處理,并找出最適合處理請求的處理程序類型。這通過查找請求的 URL 的擴展和配置文件中的信息來完成。

  HttpApplicationFactory.GetApplicationInstance創建HttpApplication實例中有三個關鍵方法:

  HttpApplicationFactory._theApplicationFactory.EnsureInited()  該方法檢查HttpApplicationFactory是否被初始化,如果沒有,就通過HttpApplicationFactory.Init()進行初始化。在Init()中,先獲取global.asax文件的完整路徑,然后調用CompileApplication()對global.asax進行編譯。

HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context)  創建特定的HttpApplication實例,觸發ApplicationOnStart事件,執行ASP.global_asax中的Application_Start(object sender, EventArgs e)方法。這里創建的HttpApplication實例在處理完事件后,就被回收。

  HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context) 該方法創建HttpApplication實例并進行初始化,調用System.Web.HttpApplication.InitInternal()方法。創建HttpApplication實例是根據實際的_theApplicationType進行創建。如果Web目錄中沒有global.asa文件,也就是說沒有動態編譯生成ASP.global_asax類型,那就直接實例化  HttpApplication。如果創建了ASP.global_asax類型,那就對ASP.global_asa進行實例化。

  創建HttpApplication實例之后就是調用實例的InitInternal方法。
  InitInternal方法的主要功能如下:
    1. InitModules():根據Web.Config的設置,創建相應的HttpModules。

    2. HookupEventHandlersForAppplicationAndModules:根據發生的事件,調用HttpApplication實例中相應的事件處理函數。

  3. 創建很多實現IExecutionStep接口的類的實例并添加到當前HttpApplication實例的_execSteps中,等待回調時執行。從這里我們可以看到HttpApplication是以異步的方式處理請求, 對請求的很多處理工作都放入了_execStep等待回調時執行。

     _execStep中主要的處理工作如下:
    1) 對請求的路徑進行安全檢查,禁止非法路徑訪問(ValidatePathExecutionStep)。
    2) 如果設置了UrlMappings, 進行RewritePath(UrlMappingsExecutionStep)。
    3) 執行事件處理函數,比如:BeginRequest、AuthenticateRequest等等。

  下面就是獲取處理當前請求的HttpHandler,ASP.NET頁面的動態編譯也是在這里進行的。至此HttpApplication流程將會轉到HttpHandler流程.也就是說HttpApplication 對象負責查找應該使用哪種處理程序來處理請求。HttpApplication 對象還負責檢測對動態創建的、表示資源的程序集(如 .aspx 頁面或 .asmx Web 服務)所進行的更改。如果檢測到更改,應用程序對象將確保編譯并加載所請求的資源的最新來源。HttpApplication調用ProcessRequest方法來處理用戶請求,此方法會調用對應的HttpHandler來處理用戶請求,HttpHandler根據用戶請求的文件的擴展名處理請求,并把請求的結果,也就是HTML發送到客戶瀏覽器.

  HttpApplication是HttpRuntime所創建的嗎? 并不是,HttpRuntime只是向HttpApplicationFactory提出請求,要求返回一個HttpApplication對象。HttpApplicationFactory在接收到請求后,會先檢查是否有已經存在并空閑的對象,如果有就取出一個HttpApplication對象返回給HttpRuntime,如果沒有的話,則要創建一個HttpApplication對象給HttpRunTime。

  關于HttpApplication這個類的方法的實現,就不再一一解釋,需要了解的,在類里面寫上一個HttpApplication單詞,然后右鍵選擇“轉到定義“,就可以看到里面的元數據了。

  從上面看出global類與HttpApplication十分緊密,其事上,global類是繼承與System.Web.HttpApplication類。

public class Global : System.Web.HttpApplication
    {

        
protected void Application_Start(object sender, EventArgs e)
        {

        }
        
//省略
    }


  假設在global類中定義變量與對象,我們在全局中是否能夠取得或設置他的值呢?看下面的例子:

Code

  在頁面中設置:
  WebApp.Global.UserName = "AAAA";
  在設置前與設置后輸出,你可以看到值的變化,但對變量的設置,會出現什么問題?這些就需要你在開發中去考慮了。

  如果使用過MVC框架開發的朋友就很熟其路由規則配置,其實就是設置在Global類的Application_Start事件中,如下面:

 public class MvcApplication : System.Web.HttpApplication
    {
        
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute(
"{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                
"UpcomingDinners",
                
"Dinners/Page/{page}",
                
new { controller = "Dinners", action = "Index" }
            );

            routes.MapRoute(
                
"Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

        }

        
protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }


  其實我們經常用的Application對象是HttpApplication類的一個屬性,至此HttpApplication已經完成,下次轉到HttpHandler流程了。

1
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()