**
最近幾天一直在看Spring的Ioc和AOP的源碼介紹,還有Webx的使用。看Spring的源代碼讓人眼花繚亂,webx的配置文件也會讓人感覺錯綜復雜無從下手。今天把之前看到的想到的webx相關的內容記下來,也當為自己的學習做一個小小的總結。
這里以經典的petstore項目為例。
首先看配置文件。當然先看web-app文件夾了。
文件夾下有common、home、store和user四個文件夾以及web.xml等6個XML文件。它們的作用是什么呢?當然是配置web容器了。這么多文件又是如何相互配合的呢?其中肯定是有相互的引用的。下面就來看一下。
首先是web.xml文件。這是最重要的一個文件,web應用啟動時就要根據其中的內容來加載容器了。看一下這個文件中的內容:
首先是三個context -param,分別配置了日志系統的根目錄、日志級別和日志的編碼格式。這些就不用多說了。接下來是兩個重要的配置:Listener。一個是LogConfigurationListener,是日志相關的;一個是WebxContextLoaderListener,這個與應用的容器相關的。它們的作用和工作原理稍后再來分析。Listener之后是兩個Filter,也是分別和日志與容器相關:SetLoggingContextFilter和WebxFrameworkFilter。然后是兩個filtermapping和兩個servletmapping。
現在來看一下WebxContextLoaderListener。顧名思義,這是一個Listener,一個監聽器。看一下源代碼。而這一個監聽器是實現了ServletContextListener接口的。其中定義了兩個方法在前者實現了,一個是public void contextInitialized(ServletContextEvent sce);一個是public void contextDestroyed(ServletContextEvent sce);顯然兩個方法的參數是事件,而函數的作用就是對參數傳進來的事件作出反應:一個是容器“initialized“,一個是“Destroyed“,也就是說,在web應用啟動和銷毀的時候作出自己的響應,也就開始了和結束了容器的生命。
然后是兩個Filter,我們來看一下WebxFrameworkFilter。配置文件里定義了filter-name、filter-class和兩個init參數。重要的是filter-class:WebxFrameworkFilter,其作用當然是對請求作過濾了。過濾的規則則是在兩個init參數中配置的。這個類繼承了FilterBean類。當應用啟動的時候,其init()方法被調用。這個函數中有一個功能就是取得了webxRootController。根據什么獲取呢,這里就用到了webx.xml以及webx-*.xml了(本文的目的是為了分析配置文件之間的關系)。
webx.xml和webx-*.xml的語法相同,作用類似,內容也非常相似。對應的是父應用和子應用。先看webx.xml的內容。首先是幾個import。把其它幾個文件引用進來了:common/webx-component-and-root.xml、common/pipeline-exception.xml、common/resources.xml、common/uris.xml、common/template-data.xml這樣就把common文件夾下7個文件中的5個引用進來了。另外通過classpath資源,把其它模塊下的三個XML文件也引用進來了。這樣在應用中就會把所有的XML文件全部利用上了。以前老沒有看到其他文件有什么用,這次終於明白了。但是還有一個問題,common文件夾下有7個文件,這里僅僅import進來了5個,還有兩個(pipeline.xml和component.xml)呢?它們都應用的配置文件(webx-*.xml)中引用到了。下面看一下每一個配置文件的作用:
pipeline-exception.xml定義了對異常的響應,即遇到異常時用哪個頁面響應;
resources.xml則定義了各種資源及其響應的loader;
uris.xml定義了發生內部或外部重定向時URI的構造;
webx-component-and-root則定義了頁面渲染的相關功能以及對URL后綴的映射;
webx-component則將框架提供的服務提供給了應用;
pipeline則是起到閥門作用的數據流管道了,這里決定了請求的方向。
此外對應着home、user和store三個文件夾下都有一個form.xml。這里的form.xml當然為應用提供表單驗證的功能。
至此,所有的配置文件的功能以及相互之間引用的關系已經分析完了。如果想對其進行擴展的話,可以自己寫一個XML文件,再被其他XML文件所import就可以了。
對配置文件的分析就到這里了,下面再看一下請求數據流程(這一部分很多地方可以找到介紹的):
一個請求對應的URL的地址部分可以分成三個部分:服務器地址、web項目和子應用。當然服務器的地址就決定了這個請求是否到本台服務器;然后再分發給某一個web應用比如說petstore。最后就送到了子應用或者具體的頁面上了。
當請求到達一個web應用內部的時候,首先請求的后綴會根據webx-component-and-root.xml中的配置做一次映射。之后請求就進入管道,其具體的流向就交由pipeline.xml決定了。pipeline中定義的操作首先是初始化tuibine,然后依次為日志上下文、URL分析獲取target(比較抽象的一個概念)、csrfToken的檢查和權限檢查;最后就是按照target來分發流向了。以后綴為null(target-extension-condition extension=”null”)的情況為例:首先是perforAction處理表單數據;然后是performTemplateScreen填充頁面內容;最后是renderTemplate 渲染頁面。其中Action和Screen對應的類分別在**.module.[action、screen]中。查找的規則是由內到外,由特定到默認的類名了。其中請求的流動過程中可能會發生重定向。這個時候為了避免硬編碼中構造URL的不便,uris.xml就派上用場了。
此外在學習的過程中還遇到了占位符的問題,在請教師兄時候才明白。例如webx.xml中的“$1“,就是說這是一個占位符,可以被前邊的place-holder定義的內容來替換。