Struts 學習記錄

  • Struts2項目的目錄組織結構
    • apps——存放了全部的Struts2的示例項目
    • docs——存放了全部Struts2與XWork的文檔
    • lib——存放了全部Struts2相關的JAR文件以及Struts2所依賴的JAR文件
    • src——存放了全部Struts2的源碼,以Maven所指定的項目結構目錄存放
    • 構成對象的基本要素
    • 簽名(Signature)——對象核心語義歸納
    • 屬性(Property)——對象內部特徵和狀態的描述
    • 方法(Method)——對象行爲特徵的描述
  • 對象構成的三種模式
    • 屬性-行爲模式:同時擁有屬性定義和方法定義,大多數對象都是這種模式
    • 屬性模式:對象只擁有屬性定義,輔之以響應的setter和gettet方法。JavaBeann、VO、DTO
      • PO(Persistent Object)——持久化對象
      • BO(Business Object)——業務對象
      • VO(Value Object)——值對象
      • DTO(Data Transfer Object)——數據傳輸對象
      • FormBean——頁面對象
    • 行爲模式:主體是一系列的方法定義,而不含有具體的屬性定義,也是一些無狀態的寫做對象。Servlet、接口實現類。
      • 方法簽名(Signature)——行爲動做的邏輯語義歸納
      • 參數(Parameter)——行爲動做的邏輯請求輸入
      • 返回值(Return)——行爲動做的處理響應結果輸出
  • 對象關係模型
    • 從屬關係——一個對象在邏輯語義上隸屬於另一個對象
      • 歸屬:是由外部世界的邏輯關係映射到編程元素之上而帶來的。在面向對象的編程語言中,主要以對象之間互相引用的形式存在
      • 繼承:多態的實現。
    • 協做關係——對象之間經過寫做來共同表達一個邏輯語義
      • 一個對象在絕大多數狀況下都不是孤立存在的,他老是須要經過與其餘對象的寫做來完成其自身的業務邏輯
      • 當對象運做在「屬性-行爲」模式上時,咱們可以最大程度地應用各類設計模式,單一的屬性模式和行爲模式對象,在設計模式的應用上很難施展拳腳。
      • 當對象運做在「屬性-行爲」模式上時,咱們可以最大程度地發揮對象之間的協做能力,對象之間的經過行爲動做的邏輯調用是對象協做的本質內容。
      • 對象建模要本着提升程序的可讀性、可維護性、可擴展性爲基本原則
  • 框架的本質
    • 框架知識一個JAR包而已,其本質是對JDK的功能擴展。
    • 是一組程序的集合,包含了一系列的最佳實踐,做用是解決某個領域的問題。
  • 最佳實踐:無數程序員在通過了無數次的嘗試後,總結出來的處理特定問題的特定方法。它可以極大的解放生產力。
    • 永遠不要生搬硬套任何最佳實踐,結合具體的業務需求因地制宜的解決問題。
    • 始終保證程序的可讀性、可維護性和可擴展性。
    • 簡單是美:消除重複,化繁入簡。
    • 儘量使用面向對象的觀點進行編程
    • 減小依賴,消除耦合:加入的外部JAR越多,就意味着程序對外部環境的依賴越高
  • 分層開發模式
    • 表示層(Presentation Layer)——負責處理與界面交互相關的功能
    • 業務層(Business Layer)——負責複雜的業務邏輯計算和判斷
    • 持久層(Persistent Layer)——負責將業務邏輯數據進行持久化儲存
  • MVC模式
    • M(Model)——數據模型:程序的核心載體,貫穿程序運行的核心內容
    • V(View)——視圖展示:Jsp
    • C(Control)——控制器:

  • Struts2的宏觀視圖:
    • 第一條主線——Struts2的初始化:init方法驅動執行
      • 盡在web應用啓動時執行一次
      • init方法的執行失敗叫致使整個Web應用啓動失敗
      • 主線初始化的兩大內容
        • 框架元素的初始化工做:包含了對框架內部的許多內置對象的建立和緩存
        • 控制框架運行的必要條件:運行期檢查
    • 第二條主線——Struts2處理Http請求:doFilter方法驅動執行
      • 第一階段——Http請求處理:依賴Web容器,並時時刻刻將與Web容器打交道爲主要工做
      • 第二階段——XWork執行業務邏輯:程序執行的控制權被移交給了XWork,這一階段的程序代碼不依賴於Web容器,徹底由XWork框架驅動整個執行的過程
    • 設計理念的解耦
      • 從代碼上進行物理解耦
      • 講邏輯分配到不一樣的執行階段
      • 嚴格意義上來講Struts2,其實是由兩個不一樣的框架所組成。
      • 將Web容器與MVC實現分離,是Struts2區別於其餘Web框架的最重要的特徵。


  • Struts2的微觀元素:
    • 第一條主線——Struts2的初始化

    • 第二條主線——第一階段Http請求的預處理

    • 第二條主線——第二階段XWork執行業務邏輯
  • Struts2配置詳解
    • 配置概覽






Struts2中的設計模式
  • ThreadLocal模式
    • Servlet對象的運行特徵
      • Servlet是一個無狀態的單例對象(Singleton)
      • Servlet在不一樣的線程池中卻共享同一個變量
      • 傳統的基於Servlet的開發模式中,Servlet對象內部的實例變量不是線程安全的
    • ThreadLocalMap變量
      • 屬於線程的內部屬性,不一樣的線程擁有徹底不一樣的ThreadLocalMap變量
      • 線程中的ThreadLocalMap變量的值是在ThreadLocal對象進行set或者隔天操做時建立的
      • 在建立ThreadLocalMap以前會檢查當前線程中的ThreadLocalMap
      • 使用當前線程的ThreadLocalMap的關鍵在因而用當前的ThreadLocal實例做爲Key進行儲存
    • 縱向隔離——線程與線程之間的數據訪問隔離。
    • 橫向隔離——同一個線程中,不一樣的ThreadLocal實例操做的對象之間相互隔離。
    • ThreadLocal與synchronized關鍵字
      • ThreadLocal是一個Java類,經過對當前線程中的局部變量的操做來解決不一樣線程的變量訪問的衝突問題,每一個線程都有其副本(空間換時間)
      • synchronized是一個保留字,依靠JVM的鎖機制來實現臨界區的函數或者變量在訪問中的原子性,鎖機制的變量時多個線程共享的
    • 數據共享仍是數據傳遞
      • ThreadLocal模式的核心在於實現一個共享環境。
      • 隨處存在的共享環境使全部開發層次耦合在一塊兒,沒法獨立測試
      • 數據傳遞應該經過接口函數的簽名顯示聲明,纔可以從接口聲明中表達接口所表達的真正含義
    • ThreadLocal模式主要步驟
      • 創建一個類,並在其中封裝一個靜態的ThreadLocal變量,使其成爲一個共享數據環境
      • 在類中實現訪問靜態ThreadLocal變量的靜態方法(設值取值)
    • 結論
      • 可使數據在不一樣的編程層次獲得有效共享
      • 能夠對執行邏輯與執行數據進行有效解耦



  • 裝飾模式(Decorator)基本含義是可以動態地爲一個對象添加一些額外的行爲職責
    • 繼承的特性
      • 現有對象行爲的覆蓋——經過覆寫(Override)父類中的已有方法完成
      • 添加新的行爲職責——經過在子類中添加新的方法完成
    • 裝飾模式的目的與特性
      • 目的——繼續擰對象行爲職責擴展
      • 特性——動態(擴展特性在運行期自動得到)
    • 裝飾模式所涉及的角色
      • 原始接口(Component)——定義了一個接口方法。
      • 默認目標實現類(TargetComponent)——對於原始接口的默認實現方式。
      • 裝飾實現類(ComponentDecorator)——一樣實現了原始接口,內部封裝了一個原始接口的對象實例TargetComponent
      • 具體裝飾實現類(ComponentDecoratorA、ComponentDecoratorB)——繼承自裝飾類ComponentDecorator,咱們能夠在operation方法中調用原始接口的對象實例TargetComponent獲取默認的目標實現類的行爲方式並加以擴展
    • 裝飾的兩點要義
      • 默認目標實現(TargetComponent)類封裝於具體的裝飾實現類(ComponentDecorator)或者其子類的內部,從而造成對象之間的引用關係
      • 具體裝飾實現類(ComponentDecorator)一樣實現了原始接口(Component)這樣一來咱們從外部調用者的角度來看待原始接口(Component)的默認目標實現(TargetComponent),就好像它被裝飾了一番,以裝飾實現類(ComponentDecorator)的形式呈現出來。
    • 比繼承更加靈活的應用場景
      • 適合對默認目標實現(TargetComponent)中的多個接口進行排列組合調度
      • 適合對默認目標實現(TargetComponent)進行選擇性的擴展
      • 適合默認目標實現(TargetComponent)未知或者不易擴展的狀況



  • 策略模式(Strategy)

    • 主要角色
      • 環境(Context)角色——持有一個Strategy類的引用,決定調用哪一種Strategy角色完成業務邏輯
      • 抽象策略(Strategy)角色——它是全部策略算法的核心概括。
      • 具體策略(ConcreteStrategy)角色——封裝了具體的側羅算法或行爲。
      • 最終目的是吧使用算法的責任(環境)和算法的實現進行解耦。
    • 策略模式的核心
      • 抽象,全部核心算法的行爲接口的抽象統一
      • 選擇,指的是在運行期不一樣的算法實現之間進行選擇
    • 優勢
      • 提供了管理一組算法族的方法——經過接口和多個算法實現之間的的契約接口來完成業務場景。
      • 提供了能夠替換經過繼承進行對象行爲擴展的方法——使用公共抽象接口的不一樣實現類而並不是一個抽象類的集成連完成的行爲的擴展。
      • 提供了將算法的調動責任預算法邏輯進行解耦的方法——經過角色轉移將調用環境角色與算法抽象之間分開,造成引用關係。


  • 構造模式(Builder)
    • 構造模式的四個角色
      • 客戶端(Client)——調用具體的構造器完成對象構建。這個角色只負責構造器的建立和選擇,對於產品的具體信息並不知曉。
      • 抽象構造器(Builder)——這是一個抽象的構造器角色,有一組接口方法扮演。
      • 具體構造器(ProductBuilder)——具體的構造器實現。其中封裝了一個目標的對象實例。
      • 產品(Product)——整個構造模式的產物。

    • 構造器的三個步驟
      • 構造器(Builder)首先會建立一個目標的實例加以緩存
      • 構造器依次調用構建目標對象特性的行爲方法,其目的在於爲目標對象蒐集並設置其內在特性
      • 構造器最終調用其核心方法build完成目標對象的建立並返回給客戶端。

  • 責任鏈模式(Chain Of Responsibility)模式

    • 主要角色
      • 請求(Request)角色——請求角色指的是擊鼓傳花中的花束
      • 執行對象(ConcreteHandler)角色——這裏的執行對象角色就是之全部的參與遊戲的人
    • 重要的特性
      • 請求在這個鏈上傳遞,知道臉上的某一個執行對象決定處理此請求
      • 鏈的存在狀態有對象的依賴協做關係決定。所以鏈能夠是直線,環,樹。
      • 負責調用責任鏈的客戶端對於究竟是哪個執行對象來進行請求的處理並不知曉


容器
  • 對象生命週期管理兩個不一樣的方面
    • 在程序的運行期,對象實例的建立和引用機制
    • 對象與其關聯對象的依賴關係的處理機制
  • 控制反轉(Inverse of Control)
    • 以此爲基礎創造了一個更加熟悉的概念,依賴注入(Dependency)
    • 對象經過其依賴對象的幫助,完成其業務邏輯的過程。
    • 每一個對象不得不依賴於其寫做的對象(也就是它所依賴的對象)的引用和構建。
    • 結論:每一個對象自身對於邏輯的執行能力,被其所依賴的對象反向控制了,這也就是控制反轉的本質含義。
  • 容器(Container)的引入
    • 交給程序去管理如何獲取以來對象的弊端
      • 對象將頻繁建立,效率大大下降。
      • 對象建立的邏輯與業務邏輯代碼高度耦合,使得一個對象的邏輯關注度大大分散
      • 程序的執行效率大大下降,因爲沒法區分明確的職責,很難針對對象實現的業務邏輯進行單元測試
    • 容器的目的是爲了解決對象生命週期管理中所遇到的問題,其要遵循必定的原則
      • 容器應該被設計成一個全局的。統一的編程元素
      • 在最大程度上下降容器對業務邏輯的入侵
      • 容器應該提供簡單而全面的對象操做接口
  • 容器中的接口的分類
    • 獲取對象實例——getInstance、getInstanceName
    • 處理對象依賴關係——inject
    • 處理對象的做用範圍策略——setScopeStrategy、removeScopeStrategy
    • 容器是一個輔助的編程元素,他在整個系統中應該被實例化爲一個全局的、單例的對象。
    • 容器在系統初始化時進行自身的初始化。
  • 容器實現的兩個方面
    • 容器的初始化需求——應該掌握好容器初始化的時機,並考慮如何對容器實例進行系統級別的緩存
    • 系統與容器的通訊機制——應該是提供一種有效的機制與這個全局的容器實力進行溝通
  • 被容器接管的對象
    • 在bean節點中聲明的框架內部對象
    • 在bean節點中聲明的自定義對象
    • 在constant節點和Properties文件中聲明的系統運行參數
    • 以上者三類對象只須要在Struts2/XWork的配置文件中進行聲明便可
  • 容器進行對象操做的幾個要點
    • 經過操做容器進行對象操做的基本前提是,當前的操做主體可以得到全局的容器實例。於是,全局的容器實例的獲取在操做主體的初始化過程當中完成
    • 經過操做容器進行的對象操做都是運行期(Runtime)操做
    • 經過操做容器所獲取的對象實例,都是受到容器託管的對象實例
    • 經過操做容器進行的依賴注入操做,能夠針對任意對象進行,該操做能夠創建起任意對象和容器託管對象之間的聯繫
  • 在容器內部進行緩存的是對象實例的構建方法,而不是對象實例自己。這就讓容器看起來像一個工廠的集合,可以根據不一樣的要求,製造出不一樣種類的對象實例











XWork
  • XWork的宏觀視圖
    • 核心分發器 不屬於Xwork框架的組成部分,但在Struts2中有着很是重要的地位。
    • XWork的控制流體系 ActionProxy、ActionInvocation、Interceptor、Action、Result組成
    • XWork的數據流體系 ActionContext和ValueStack組成了XWork在進行請求響應時所依賴的一個數據環境。
    • 調用關係 核心分發器驅動着XWork框架的調用執行
    • 映託關係 XWork框架的控制流體系的執行基礎是數據流中的元素 數據流的元素由於控制流的執行才存在乎義。
      • 解耦和 XWork將數據流和控制流這兩大驅動程序運行的基本力量進行了物理隔離,將它們分派到不一樣的執行元素上,但在運行期間二者又經過某種編程手段郵寄的聯繫在了一塊兒,這種看似很鬆實際很緊的聯繫正式貫穿XWork框架整體設計的一個核心思想。
  • XWork的微觀視圖
    • 數據元素流
      • ActionContext——數據環境  請求的參數、處理的返回值、甚至一些原生的Web容器對象都封裝與ActionContext內部
      • ValueStack——數據訪問環境 其中主要做用是對OGNL計算進行擴展,其賦予了ActionContext數據計算的功能。
      • 結論:XWork對於數據流設計的亮點在於數據流元素設計成獨立的數據結構。
  • 控制流元素
    • XWork認爲,一個事件處理的流程是有規律並能夠被繼續細化的。
    • Action——核心處理器(屬性——行爲模式)
    • Interceptor——攔截器 自己屬於AOP的概念
    • Result——執行結果  被定義爲一個獨立的邏輯執行層次,組要做用是是核心處理類Action可以更加關注核心業務流程的處理,而將程序的跳轉控制邏輯交給Result來完成
    • 總結出來就是:一個完整的事件處理流程可定義爲:以ACtion爲業務處理核心,Interceptor進行邏輯輔助,Result進行響應邏輯跳轉的具備豐富的執行層次的事件處理體系。
    • 以上三個對象在事件處理流程進行規範化中完成了前兩個步驟,①劃分事件處理流程步驟②定義事件處理節點對象。整個規範化流程中最爲關鍵的步驟也就是③組織事件處理節點對象的執行次序
    • ActionProxy——執行環境 其重要做用就在於對外屏蔽整個控制流核心元素的執行過程,對內則爲Action、Intercep、Result等事件處理節點對象提供一個無干擾的執行環境
    • ActionInvocation——核心調度器 其被封裝於ActionProxy的內部,是XWork內部真正事件處理流程的總司令。
    • XWork的設計理念始終是將邏輯職責分派的最合適的編程元素之上

  • 小結
    • XWork的基本設計原理的別具匠心體如今兩個方面~
      • XWork對於請求——響應模式纔去的是顛覆傳統Servlet模式的實現方式
      • XWork對於事件處理流程的定義,突破了」單一元素「和」順序執行「這兩大壁壘


深刻XWork宏觀視圖
  • 數據流體系  數據流有兩大特性:數據和流
    •  」數據「強調的是數據做爲一個載體
    • 」流「強調的是一個動態的過程,也就是數據訪問和數據傳輸
    • ActionContext雖表現出來的空間的概念,剛好成爲數據載體進行儲存的自然基石,它既負責數據存儲又負責數據共享
    • ValueStack是一個具有表達式引擎計算能力的數據結構
    • XWork將ValueStack至於ActionContext中的目的在於僞靜態的數據添加動態計算的功能
    • ActionContext沒法脫離ValueStack單獨存在,不然全部的數據載體就如一潭死水。失去了流動性的數據流,只能稱之爲數據載體而非數據流
    • ValueStack沒法脫離ActionContext而單獨存在不然ValueStack就沒有了數據計算的基礎、失去了數據的數據流,只能稱之爲一個表達式計算工具而非數據流。


  • 控制流
    • 兩層主要關係①事件處理節點與事件驅動元素之間的關係②核心事件處理節點與輔助事件處理節點之間的關係
    • 事件處理節點(Action、Interceptor、Result構成)與驅動元素控制流元素(ActionProxy、ActionInvocation構成)的兩類
    • 在XWork的控制流中,事件處理驅動元素對事件處理節點元素造成調用關係
    • Action和Interceptor之間的關係
      • 在整個棧結構中,除了位於棧底的Action之外,棧中的其餘元素都是Interceptor對象
      • 因爲Action位於棧的底部,試圖執行Action時,咱們必須把位於Action之上全部Interceptor依次拿出來執行
      • 每一個位於棧中的Interceptor,除了須要完成它自身的邏輯外,還須要指定下一步的執行對象
    • XWork對於Action和Interceptor的設計,充分體現了三個核心設計理念
      • 對於事件處理,可以進行進一步的規範化的流程細化
      • 對於細化的流程,可以具有高度的可擴展性
      • 流程細化後的事件處理節點之間表現出明顯的執行層次

數據流體系——相互依存
  • ActionContext——一個平行世界
    • 數據存儲空間  其中的Map類型的變量Context是其真正的存儲空間
    • 數據共享空間 知足線程安全的判別標準
      • 進行數據共享的數據信息是不是類的內部實例變量
      • 外部對共享數據的訪問是否存在多線程環境
    • 數據存儲內容  從ActionContext對外提供的訪問接口分爲不一樣的類型
      • 對XWork框架對象的訪問——getContainer、getValueStack、getActionInvocation
      • 對數據對象的訪問——gerSession、getApplication、getParameter
      • 被封裝後的SessionMap等對象,可以進一步保證數據訪問的線程安全性
      • 保持全部存儲對象的Map結構,能夠統一數據訪問方式


  • ValueStack——對OGNL的擴展
    • ValueStack針對OGNL計算的擴展,其實是針對OGNL三要素中的Root對象進行擴展 分爲兩個部分
      • ValueStack從數據結構的角度被定義爲一組對象的合集
      • ValueStack規定在自身這個集合中的全部對象,在進行OGNL計算式都被視做是Root對象
    • ValueStack的數據結構 具備棧的數據結構
      • 棧是一個容器,能夠存放多個對象
      • 棧是先進後出的鏈表結構
      • ValueStack是一個被設計成」棧「的數據結構,而且仍是一個具有表達式引擎計算能力的數據結構
      • ValueStack成爲了Struts2/XWork框架進行OGNL操做的一個窗口
      • ValueStack是XWork框架進行OGNL計算的場所
      • ValueStack是XWork框架進行數據訪問的基礎
    • ValueStack對OGNL計算規則的影響——無差異化
      • 從棧的頂端開始對每一個棧內元素進行表達式匹配計算,並返回第一個成功匹配的表達式計算結果
      • 支持多個」根對象「操做的基本流程是自上而下遍歷其中的元素逐一進行表達式求值計算,返回第一個成功匹配的表達式的計算結果其本質就是棧內元素遍歷
    • 棧頂元素和子棧
      • 一個大小爲N的ValueStack,除了自身外,有N-1個子棧
      • 每個子棧自身也是一個ValueStack,相對於ValueStack造成了一個遞歸的數據結構
  • 深刻ValueStack的實現
    • CompoundRoot調用cutStack方法返回一個子棧的結構
    • CompoundRootAccessor


  • 如影隨行。相互依存的ActionContext與ValueStack的兩個重要結論
    • ActionContext的建立,老是伴隨着ValueStack的建立
    • Valuestack的上下文環境與ActionContext的數據存儲空間是等同的

控制流體系——有條不紊
  • Action——革命性突破
    • Action的定義提供了一些額外的信息
      • 方法主體——Action接口的具體實現類是XWork進行核心業務邏輯處理的場所
      • 運行參數——都以Action中樞性變量的形式出現
      • 返回值——起到流程控制的標誌做用
    • POJO模式與Servlet模式的比較
      • 分歧的核心在於具體負責請求處理的核心響應類是不是一個有狀態的對象
      • 請求數據——參數,仍是屬性變量?
      • 響應數據——參數、返回值,仍是屬性變量?
      • 響應邏輯跳轉——返回值仍是參數?
      • 對於請求數據,參數比屬性變量更爲直觀,也更符合Java原生的語法含義
      • 對於響應數據,最適合的表達方式是方法的返回值
      • 使用有狀態的POJO對象來進行請求響應,在數據訪問上具備自然的優點
    • 狀態與動做的合體
      • 突破了傳統Servlet模式中相應對象對Web容器的依賴
      • 突破了傳統Servlet模式中響應對象無狀態的限制,在響應類中將看不到任何對Web容器對象的引用
      • 對於有狀態的響應類,響應類的屬性變量是描述自身狀態的核心元素,也是響應方法進行邏輯處理的核心數據依賴
      • 屬性特性 對象的屬性特徵主要表述對象的三個不一樣特性
        • 對象自身的狀態——成爲XWork進行數據訪問的基礎
        • 對象與其餘對象之間的從屬關係
        • 對象與其餘對象的協做關係——成爲Action與業務邏輯操做接口進行整合的基礎
      • 行爲特徵 就是指對特定請求進行響應的過程
        • XWork的Action是一個狀態與動做的合體



  • Interceptor——騰飛的翅膀——Interceptor其本質是一個代碼段
    • AOP相關概念
      • 切面(Aspect)——一個關注點的模塊化,這一關注點的實現可能橫切多個對象,而這個模塊化的過程由Interceptor來實現
      • 通知(Advice)——在特定的鏈接點,AOP框架執行的動做。類型包括Before通知、After通知、Around通知和Throw通知等。
      • 切入點(Pointcut)——指定一個通知將被引起的一系列鏈接點的集合。
      • 鏈接點(Joinpoint)——程序執行過程當中明確的點,如方法的調用或特定的異常被拋出。
    • Interceptor的概念與基本的AOP概念之間的對應關係
      • 切面(Aspect)——Interceptor實現
      • 通知(Advice)——環繞通知(Around通知)
      • 切入點(Pointcut)——Action對象
      • 鏈接點(Joinpoint)——Action的執行
      • 結論在XWork中所定義的Interceptor,是一組環繞在切入點(Action對象)的執行切面,能夠在Action調用以前或者以後執行,從而對Action對象起到攔截做用。
      • Interceptor在框架中所表現的出的特色
        • 羣居——interceptor對象是一個羣居對象,在同一時刻總有多個Interceptor對象同時存在並協同工做
        • 棧結構——相互包裹造成了數據結構上的棧結構
        • 棧內元素
        • 執行棧
    • Interceptor的定義
      • 參數ActionInvocation是XWork控制流元素中的核心調度元素,使用其做爲做爲參數基於兩點考慮
        • 便於Interceptor隨時與控制流和數據流的其餘元素溝通—— ActionInvocation不只包含對控制流元素的訪問接口,同時也包含對數據流元素的訪問接口
        • 便於ActionInvocation在Interceptor的內部進行執行調度
        • 調用ActionInvocation的invoke方法來指定對執行棧的進一步調度執行,invoke方法的調用觸發了執行棧中剩餘Interceptor對象和Action對象的執行完成並返回結果
        • 直接返回一個String類型的ResultCode來中指執行棧的調度執行
    • AOP仍是IoC
      • Spring是用IoC來實現AOP,Spring經過實現容器完成對象生命週期和關聯關係的管理。
      • Spring和XWork對於AOP實現之間的本質區別就在於二者對於切入點的定義徹底不一樣,也就是攔截器所攔截的對象不一樣。Spring主要偏重的是方法級別的AOP攔截,而XWork則針對Action對象進行攔截。
      • 攔截器自身的邏輯都離不開經過對攔截對象狀態的改變而進行的行爲擴展
      • XWork中的Interceptor的主要職責,就是經過對Action狀態的改變而對Action的行爲進行擴展
      • Action自己做爲一個運行在屬性-行爲模式上的對象,其內部主要表現出一下三個方面的特質
        • 構成Action這個響應類與外部環境的交互接口
        • 構成Action這個響應類的請求數據和相應數據
        • 構成Action的行爲動做與業務邏輯處理對象之間的協做關係
        • 結論XWork是用AOP來實現IoC
    • Interceptor的邏輯意義
      • Interceptor對象的引入其實是對事件處理流程中主要職責和次要職責的有效劃分,並讓每個執行層次都可以完成其必要的職責歸屬
      • Interceptor對象的引入可以極大地豐富整個事件處理流程的執行層次,從而爲實現AOP片成打下堅實的數據結構基礎
      • Interceptor對象的引入可以是的責任鏈模式在整個執行棧的調度過程當中順利實施,從而改變事件處理流程中的順序處理邏輯,天然造成AOP模型的雛形




  • ActionInvocation——核心調度
    • ActionInvocation接口中的邏輯分類
      • 對控制流元素和數據流元素的訪問接口——getAction、getActionProxy、getStack等
      • 對執行調度流程的擴展接口——addPreListener、setActionEvenListener
      • 對執行棧進行調度執行的接口——invoke、invokeActionOnly
    • ActionInvocation調度分析
      • invoke方法是對Interceptor對象和Action對象共同構成的執行棧進行邏輯執行調度
      • 若是執行棧中的下一個元素是Interceptor對象,那麼執行該INterceptor
      • 若是執行棧中的下一個元素是Action對象,那麼執行該Action對象
      • 若是執行棧中找不到下一個執行元素,那麼執行停止,返回執行結果ResultCode
    • XWork時間處理流程所支持的三種不一樣的攔截方式
      • before攔截——invoke以前執行
      • after攔截——invoke以後執行
      • PreResultListen攔截——再Interceptor和Action執行完畢以後、Result執行以前執行
    • 在攔截器的邏輯實現中,對ActionInvocation的Invoke方法實施了遞歸調用,invocation.invoke的調用成爲邏輯上的分水嶺
      • 遞歸調用使得位於分水嶺以後的的代碼邏輯被暫時封存,等待完整的遞歸調用結束以後才能繼續執行
      • 遞歸調用使得在執行棧中的下一個元素將被拿出來執行。從表面上看造成了棧結構的順序遍歷,實際上卻造成了遞歸調用的嵌套,這就意味着在分水嶺以前的邏輯代碼將隨着棧結構的遍歷順序執行
      • 當整個遞歸調用完成以後,狀況剛恰好相反,本來最後一個執行的元素對象將首先執行在分水嶺以後的代碼邏輯,從而觸發整個逆序的執行過程
    




  • ActionProxy——執行窗口,XWork事件處理框架的總代理
    • ActionProxy的首要職責是維護XWork的執行元素與請求對象之間的配置映射關係
    • ActionProxy構建方法createActionProxy方法的參數主要分爲兩類
      • 配置關係映射——namespace、actionName、methodName等
      • 運行上下文環境——extraContext
    • 真正的XWork控制流元素都被ActionProxy有效地隱藏在了背後



  • 交互體系——水乳交融  數據流和控制流之間的交互體系



  • 數據環境的生命週期
    • 做爲Xwork的數據環境,ActionContext的數據內容在整個XWork控制流的生命週期中共享
    • 數據流的生命週期比控制流的生命週期更長,ActionContext是一個橫跨了整個XWork控制流執行週期的元素
    • ActionContext所進行的數據共享,不只對整個XWork的控制流元素有效,他甚至對整個當前執行線程有效
    • 做爲數據環境,Actioncontext是隱藏於XWork控制流執行背後的重要元素,成爲控制流元素與數據流元素的溝通橋樑
  • 三軍會師之地
    • 控制流中的核心處理元素Action,被置於數據流元素ValueStack中。
    • 在傳統的請求——響應的實現模式中,不管是參數——返回值模式仍是參數——參數模式,控制流元素對於數據流元素都是有絕對的掌控權的。
  • Action交互體系 體現了Action交互體系的三個不一樣方面
    • 外部環境交互體系——構成Action與外部環境的交互接口
      • 是指Action與Web容器中HttpServletRequest、HttpServletResponse、HttpSession對象的交互過程
      • ServletConfigInterceptor這個攔截器爲咱們打造了一個對Action進行擴展的範例,打造分爲三個過程
        • 定義一個藉口
        • 讓Action實現該接口
        • 在攔截器終將Action強制轉化爲接口,完成接口方法的邏輯調用
        • 這三個過程的代碼邏輯調用蘊含了兩種不一樣的Action擴展結果
          • 經過Action實現的接口,向Action傳遞外部信息
          • 經過Action實現的接口,完成功能的擴展
          • 這種交互方式主要依據其實是面向對象概念中實現類與接口之間的關係
    • 數據交互體系——構成Action的請求數據和響應數據
      • 反映了Action與數據流元素進行交互的過程(由ParametersInterceptor攔截器完成)

      • ParametersInterceptor是一個將外部環境數據與Action的屬性變量進行融合的骨架,而其中的retrieveParameter方法,就是外部環境數據的提供者
      • 其實是提供了一個數據環境映射到Action對象的途徑和方法
    • 協做交互體系——構成Action與業務邏輯處理對象之間的協做關係






運行主線篇
一應俱全——Struts2初始化主線
  • 配置元素與初始化主線
    • 從入口程序開始(兩大主線的入口都是StrutsPrepareAndExecuteFilter
    • init方法的主要內容是針對三個元素展開,而這三個元素也成爲以後Http請求處理這一條邏輯主線的執行依據
      • Dispatcher——核心分發器
      • PrepareOperations——Http預處理類
      • ExecuteOperations——Http處理執行類
      • createDispatcher方法filterConfig中所包含的參數其實來自於Web.xml的初始化參數配置
  • 初始化主線的核心驅動力
    • 核心驅動力的邏輯——對於程序運行目的的描述
    • 核心驅動力的形式——推進程序運行的編程元素
    • 數據結構——框架的核心配置元素
    • 算法——圍繞着核心配置元素的初始化過程
    • 框架的核心配置是一種貫穿始終的核心驅動力,他不只可以以必定的形式表現出框架的構成元素互相之間的邏輯關係,同時可以將它們的執行邏輯串聯起來
    • Struts2初始化主線的核心驅動力,正式對各類配置形式所進行的一次統一的對象化處理
    • Struts2在初始化的時候,將各類各樣的配置元素,不管是XML形式仍是Properties文件形式(甚至多是其餘自定義的配置形式)轉化爲Struts2所定義的Java對象或者Struts2運行時的參數的處理過程。
  • 初始化主線的構成元素 對多種多樣的配置進行管理
    • 對配置元素進行操做的流程元素由三個不一樣的類別構成
      • 配置元素的加載器——將紛繁複雜的配置表現形式轉化爲框架元素
      • 配置元素的構造器——對框架元素進行初始化操做,使用的是構造模式
      • 配置元素的管理類——在初始化主線運行的過程當中,對配置元素的數據的存儲和配置元素的初始化行爲進行控制。
核心分發器——Dispatcher
  • 核心分發器的核心驅動做用(起——承——轉——合)
    • 起——負責系統初始化
    • 承——接收並預處理Http請求
    • 轉——將Struts2轉入XWork,經過ServiceAction方法進行請求轉發
    • 合——垃圾清理,cleanup
      • 對於在整個請求週期中定義了完整的生命週期的框架元素的清理
      • 對於線程安全的ThreadLocal對象的清理
    • 針對Dispatcher的重要結論
      • 做爲一個線程安全的對象,Dispatcher涵蓋了Struts2的整個生命週期。不管是Struts2的初始化,仍是處理Http請求,實際都在Dispatcher中完成
      • Dispatcher是Struts2與XWork的分界點,也是將MVC實現與Web容器隔離的分界點

配置元素的加載器(Provider)
  • 配置元素的加載器的做用
    • 配置加載接口的各類實現類(Provider)架起了各類配置表現形式到Java世界的橋樑
    • ConfigurationProvider爲統一的操做接口,其使用了接口多重繼承機制,好處在於可以使Struts2在進行配置加載時擁有比較統一的操做路徑和操做方法
  • 容器加載器——ContainerProvider
    • 不一樣的ContainerProvider之間並無依賴關係
    • 進行配置加載的生命週期:先進行初始化(調用init方法),再進行元素註冊(調用register方法)
  • 事件映射加載器——PackageProvider
    • PackageConfig所提供的兩個構造函數都被定義成了Protected,沒法經過正常的構造函數的途徑直接構造一個Package
  • 配置元素的構造器(Builder)
    • 構造器自身是一系列操做方法的集合類
    • 操做方法可分爲兩種不一樣的類型,非別對應於構造器進行對象構造的兩個步驟
      • 參數蒐集操做
      • 建立對象操做
  • 容器構造器——ContainerBuild
    • 蒐集參數——factory方法、alias方法、constant方法
    • 構造對象——create方法
  • 事件映射構造器——PackageConfig.Builder
    • 他不只是一個內部類,仍是一個具體的實現操做類而非一個接口
    • ContainerBuilder進行初始化時並不關係容器自身的數據結構,而是強調容器中元素的蒐集過程,因此定義成接口
    • 因爲PackageConfig全部構造函數都被設置成protected,從而使得針對PackageConfig的構造器也不得不定義成一個內部類
    • PackageConfig.Builder做爲」構造器「的特色
      • Builder構造器中絕大多數操做的返回值都是這個構造器自己,這有助於程序員在構造PackageConfig時使用鏈式操做方式進行連續調用。
      • 外部程序構造PackageConfig的惟一途徑是使用這個PackageConfig.Builder構造器,由於PackageConfig自身的構造函數被定義成了protected(隔離性)
      • Builder構造器的核心方法build在蒐集屬性值並建立真正的PackageConfig對象時,調用Collections中的unmodifiableList方法進行不可變處理(穩定性)

配置元素的管理類
  • 初始化三大核心要素(Dispatcher、Provider、Builder)
    • 初始化主線的核心驅動力
    • 初始化主線的操做載體
    • 初始化主線中元素的構建方式
  • 初始化驅動元素
    • ConfigurationManager是整個配置元素進行操做的代理接口類
    • 對全部配置元素的初始化進行調度的是Configuration對象
  • 配置管理元素——Configuration
    • Configuration主要目的就是爲了對初始化主線中的配置元素進行管理,也被成爲配置管理元素
    • 對配置元素進行管理實際上蘊含了兩個不一樣的方面
      • 提供框架級別對全部配置元素的訪問接口操做
      • 對全部配置元素進行初始化調度
    • configuration對象對於配置元素的調度本質,是對框架配置元素的操做
    • 全部的配置元素都被完整地封裝在DefaultConfiguration之中,成爲Configuration盡心配置元素管理的數據基礎
  • 配置操做接口——ConfigurationManager


Struts2初始化主線詳解
  • 核心分發器的初始化

    1. 建立ConfigurationManager
      1. 是一個配置值操做接口,也是以後對全部配置元素進行的操做調度句柄
      2. XWork的配置經過name屬性來支持一個接口的多種實現方式共存。
    2. 初始化各類配置加載器
      1. ConfigurationManager將不一樣類型的配置元素的加載接口進行區分的場所
      2. 配置加載器在此時是不會進行邏輯調用,而是在初始化容器中完成行爲邏輯,這體現出了Struts2在設計時始終遵循着」初始化「和」行爲邏輯「分離的原則
    3. 初始化容器
    4. 執行額外的初始化工做

  • 容器的初始化
    • 容器的建立過程——init_PreloadConfiguration()
    • 容器的依賴注入——container.inject(this)
    • 容器初始化的步驟爲五步
      1. 定義容器構造器——將Properties文件中的鍵值對與ContainerBuilder關聯
      2. 使用ContainerBuilder進行參數蒐集——ContainerBuilder的各類實現的核心邏輯不過是ContainerBuilder蒐集參數的過程
      3. 使用ContainerBuilder進行容器建立
      4. 初始化時間映射元素PackageConfig——填充Configuration對象中的事件映射配置對象
      5. PackageConfig進行運行期改造


與Http請求的戰鬥——Struts2是一個運行於Web容器的表示層框架,其核心做用是幫助咱們處理Http請求
  • 編程資源
    • OGNL——表達式引擎,假期外部世界與Java世界
    • XWork——請求處理器,將請求劃分爲若干處理步驟並分派到不一樣處理元素調度執行
  • 請求處理主線主要可概括爲兩個方面
    • 代碼上的物理解耦——兩個階段分屬於不一樣的框架主導執行
    • 邏輯職責上的解耦——兩個階段的主要職責徹底不一樣

  • Http請求的預處理階段
    • Dispatcher——核心分發器,執行Struts2處理邏輯的實際場所
    • PrepareOperations——Http預處理類,對全部的Http請求進行預處理
      • StrutsPrepareFilter
      • 步驟1——設置Encoding和Locale
      • 步驟2——建立ActionContext,爲了以後XWork可以在非Web容器環境下接手Http請求的處理工做打下堅實的基礎
      • 步驟3——將核心分發器Dispatcher綁定至當前線程
      • 步驟4——對HttpServletRequest進行必定的封裝
      • 步驟5——根據Http請求查找ActionMapping
    • ExecuteOperations——Http處理執行類,執行Http請求的場所
      • StrutsExcuteFilter
      • XWork框架的相關邏輯實際上由Dispatcher建立並負責驅動執行
      • Dispatcher負責Http請求不一樣處理階段的數據轉化工做,從而保證代碼在不一樣執行階段的無縫切換
      • 在XWork框架的調用接口ActionProxy中,咱們將再也不看到任何與Web容器相關的對象


  • Xwork處理階段
    • ActionProxy的數據源
      • 配置關係映射——namespace、actionName、methodName
      • 運行上下文環境——extraContext
      • Action在建立時所依賴的上下文環境與ActionProxy初始化時因此依賴的上下文環境是等同的
    • ActionInvocation的初始化
      1. 建立上下文環境
      2. ActionInvocation對象的共享
      3. 建立Action對象
      4. 將Action對象置入ValueStack中
      5. 建立ActionInvocation的上下文環境
      6. 將攔截器堆棧置於初始調度狀態
    • ActionInvocation調度的再分析
      • 執行方法的參數——沒有參數
      • 執行方法的返回值——String或者Result對象


讓視圖放開手腳
  • 視圖概述
    • Jsp技術
      • 解決了頁面視圖的構建問題
      • 解決了與服務器端進行數據溝通的問題
    • Servlet技術
      • 全部的JSP在運行期都被編譯成Servlet在Web容器中運行
      • HttpServletRequest對象主要用於處理整個Http生命週期中的數據
      • getParameter系列的方法是服務器端程序獲取瀏覽器所傳遞參數的主要接口
      • HttpServletResponse對象主要用於處理Http的響應結果
  • 視圖的本質
    • 瀏覽器是視圖層的表現載體,全部視圖層的交互職責都是經過瀏覽器進行的操做
      • 溝通協議——Http協議
      • 請求內容——Http請求:HttpServletRequest
      • 響應內容——Http響應:HttpServletResponse
      • 視圖的本質是Web容器對象HttpServletRequest和HttpServletResponse對瀏覽器行爲的控制
  • 視圖的職責
    • 視圖內容呈現——以HTML爲基礎進行的構建
    • 數據和邏輯呈現——以Java語法爲基礎進行的構建
    • 只要實現了試圖的兩大職責,它就能稱爲一個「合格」的視圖表現技術。
      • 模版技術
      • Ajax技術
      • Flex技術



Result機制
  • Result的不一樣視角
    • XWork視角——事件處理節點
      • 從XWork來看,他只是咱們對事件處理流程步驟的劃分結果而已
      • 他將告訴程序該何去何從,成爲在整個XWork控制流元素中實施控制職責的重要體系元素
    • Struts視角——視圖的操做窗口
      • Result對象那個在Struts2中看做是視圖的操做窗口,至關於完成了Servlet對象中HttpServletResponse的職責
    • Result職責分析
      • Result最大的職責,就是架起Controller層到View層的橋樑
        • 須要一個起到中轉做用的對象,完成程序執行權的轉移
        • 須要一個接口與實現分離的機制,將XWork與Struts2進行解耦和
        • 須要一個Web容器的代理對象,屏蔽底層對象的操做細節
      • 實現上的三個不一樣方面
        • 封裝跳轉邏輯
        • 準備顯示數據
        • 控制輸出行爲

標籤庫
  • 產生的初衷
    • 消除在Html代碼中的Java代碼,以一種自定義的擴展標籤來代替本來須要Java代碼表達的業務邏輯
    • 避免在JSP頁面中使用Java代碼,業務邏輯與顯示分離的目的,提升JSP自身的關注度
    • 將數據展現完全抽象成爲一個獨立的功能模塊,可以規範編程。
  • 優點
    • 標籤庫可以對HTML的許多標籤進行功能擴展
    • 在必定程度上解決了在JSP頁面中避免頻繁使用Java代碼的狀況
    • 可以極大程度地封裝成塊的HTML代碼,進而造成一套完整的頁面組件
    • 標籤庫有利於組件化開發
  • 趨勢
    • 指定標準標籤庫JSTl,視圖統一絕大多數的標籤
    • 藉助IDE的幫助,打造更多更豐富的Web層組建,並增強AJAX等功能
    • 將成熟的JavaScriptUI框架改形成標籤的形式
    • 隨着EL的逐步推廣,在JSP中使用EL也越來月可以被你們接受
  • 改革
    • 放棄Taglib,推崇模版技術
    • 不實用Taglib來構造頁面組建,而更多采用JavaScript技術豐富頁面展現
    • 直接放棄使用HTML爲模版的頁面展示方式,改用Flex等Flash表現方案
  • 標籤分類
    • 邏輯控制類——控制頁面輸出邏輯
      • c:if——分支判斷
      • c:forEach——循環
      • c:choose/c:when/c:otherwise——分支判斷
      • c:catch——異常處理
    • 數據輸出類——與服務器端進行數據溝通並以必定格式進行輸出
      • c:out——輸出表達式的值
      • c:url——輸出格式化Url
      • c:set——設置表達式的值
      • c:param——設置參數
      • fmt:message——輸出資源文件中的值
      • fmt:formatDate——格式化輸出日期
      • fmt:formatNumber——格式化輸出日期
    • 頁面組件類——將頁面元素的功能進行組件化編程

數據訪問哲學
  • 從哪裏去獲取數據
  • 取過來的數據如何顯示
  • HttpServletRequest對象主要用於處理整個HttpServletRequest生命週期中的數據
  • 傳統意義上的數據訪問,就是針對HttpServletRequest對象的讀取操做
  • ValueStack
    • ValueStack是真個Struts2進行數據訪問的實際操做句柄,而Action做爲ValueStack的Root對象,其中的屬性變量天然而然成爲了數據訪問源
    • 對於請求-響應模式實現機制上的分歧,是形成數據訪問模式差別的根本緣由
  • 數據訪問長什麼樣
    • 數據訪問的困境,主要仍是由於數據模型在某些層次的展示缺少足夠的表現力。
    • 視圖層不只應負責與服務器短的數據溝通,還應該將得到的數據進行格式化輸出。



Struts2的擴展機制
  • 可維護性——程序應具有簡單有效的方法對軟件的功能模塊進行修改和維護
  • 可擴展性——程序應具有簡單有效的方法對軟件的功能模塊進行添加和擴展
  • 始終保證程序的可讀性。可維護性和可擴展性。


程序擴展機制——插件模式(Plugin)
  • 插件——能夠即插即用的組件
    • 組件——體現了插件的功能性
    • 即插即用——體現了插件的靈活性和獨立性
  • 軟件功能模塊化
    • 儘可能將程序中的雙向依賴關係變成一種單項的集中依賴關係
  • 核心程序與功能模塊
    • 抽取各個功能模塊的公共邏輯成爲一個獨立的核心功能模塊



    • 爲核心功能模塊添加對其餘功能模塊的執行調度功能
    • 核心程序對功能模塊的調度
    • 各個功能模塊僅僅依賴於核心程序,功能模塊與功能模塊之間並無依賴
    • 功能模塊保持獨立不會互相影響

  • 利弊分析
    • 軟件運行環境——能夠運行基礎功能模塊的基礎構件,俗稱爲程序骨架
    • 功能模塊——運行在特定環境中的軟件功能分類
  • 優勢
    • 軟件模塊的管理變得更加容易
    • 軟件功能的可塑性和擴展性更強
    • 軟件的產品化和定製化成爲可能
  • 缺點
    • 軟件運行環境質量的優劣,將直接影響整個軟件的質量
    • 軟件環境的版本升級將致使依賴於該環境的全部插件失效


Struts2的插件模式
  • 深刻Struts2插件
    • 表現形式
      • 框架的本質就是JAR
      • 插件所在的JAR包,必須位於Web應用程序的CLASSPATH下
      • 在JAR包內的根目錄位置,應該存放一個名爲Struts-plugin.xml的文件
      • struts-plugin.xml的文件與Struts2的基礎配置文件struts.xml的格式相同
    • 安裝使用
      • 插件是否位於CLASSPATH下
      • 是否在JAR根目錄中存在一個名爲struts-plugin.xml的配置文件
    • 依賴關係
      • Struts的插件對Struts2的核心JAR構成依賴
      • 各插件之間原則上不造成相互依賴的關係
      • Struts2的各個插件在唄Struts2的核心程序加載時,其順序是隨機的。
    • 擴展點
      • struts-plugin.xml文件的名稱和所處的位置成爲了核心程序與插件的通訊接口
      • struts-plugin.xml文件的內容結構成爲了插件對核心程序進行擴展的依據
      • 擴展點分爲三類
        • 定義新的事件映射關係對象(Action。Interceptor、Result等等)
        • 引入新的接口定義實現或者運行參數,將其歸入Struts2的容器進行管理
        • 覆蓋Struts二、XWork的默認接口實現機制
    • 插件分類
      • 框架整合類插件
      • 簡化配置類插件
      • 功能擴展類插件
    • Struts2的插件加載機制
      • 插件加載概述,加載順序
        • struts-default.xml——位於Struts2核心JAR包的根目錄下——最早被加載,用於指定Struts2的一些默認行爲
        • struts-plugin.xml——全部插件所在的JAR包的根目錄下——緊接着被加載,,Struts2會搜索全部的CLASSPATH中的JAR文件,查找其中的struts-plugin.xml文件,這些文件的加載順序是不肯定的
        • struts.xml——位於應用程序的CLASSPATH下——最後被加載,是應用程序中Struts2的基礎配置文件,指定應用程序級別的Struts2行爲
      • 配置加載接口定義,這個過程由init_TraditionalXmlConfigurations方法完成
      • 配置加載接口的使用StrutsXmlConfigurationProvider的使用過程
        • Struts2的插件被設計成獨立於應用程序的JAR包,使得安裝盒使用變得極其簡單
        • Struts2對於核心程序、插件以及用用程序之間的關係處理的頗有條理,使得這三者之間雖然具有了豐富的層次關係,也不至於形成混亂
        • Struts2對於插件的構成要求很低,擴展點卻不少,使得咱們在模塊化設計的過程當中,有更多的餘地。


















相關文章
相關標籤/搜索