日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Struts2中的Action

發布時間:2024/9/21 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Struts2中的Action 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多數的MVC框架中的Control層,都是一個Java對象。按照慣例,我們通常會把這個層次上面的Java對象統稱為Action層。本篇文章,我們就來簡單介紹一下Struts2中Action的相關內容。?

Action的定義?

傳統的MVC框架中,Control層一般都是一個類似與Servlet的一個Java對象。因為從職責上講,Control層需要完成以下的職責:?

1. 接收從Web容器傳遞過來的參數,并做恰當的類型轉化?

2. 調用邏輯處理?

3. 搜集數據,并返回到視圖?

而在這個其中的第一步和第三步,都離不開Web容器中的對象的處理。?

Struts2中的Action,與其他傳統的MVC框架不同,使用了XWork的Action來構造Control層。讓我們首先來看看Action的接口定義:?

Java代碼??
  • /**?
  • ?*?All?actions?may?implement?this?interface,?which?exposes?
  • ?*?the?execute()?method.?However,?as?of?XWork?1.1,?this?is?
  • ?*?not?required?and?is?only?here?to?assist?users.?You?are?
  • ?*?free?to?create?POJOs?that?honor?the?same?contract?
  • ?*?defined?by?this?interface?without?actually?implementing?
  • ?*?the?interface.?
  • ?*/??
  • public?interface?Action?{??
  • ??
  • ????/**?
  • ?????*?Where?the?logic?of?the?action?is?executed.?
  • ?????*?
  • ?????*?@return?a?string?representing?the?logical?result?of?the?execution.?
  • ?????*?????????See?constants?in?this?interface?for?a?list?of?standard?result?values.?
  • ?????*?@throws?Exception?thrown?if?a?system?level?exception?occurs.?
  • ?????*???????????????????Application?level?exceptions?should?be?handled?by?returning?
  • ?????*???????????????????an?error?value,?such?as?Action.ERROR.?
  • ?????*/??
  • ????public?String?execute()?throws?Exception;??
  • }??


  • 我們只需要實現這個接口,就可以在其中編寫業務邏輯完成我們的功能。?

    Java代碼??
  • public?class?Index?implements?Action?{??
  • ??
  • ????private?static?final?long?serialVersionUID?=?-1070481751569420550L;??
  • ??
  • ????/*?(non-Javadoc)?
  • ?????*?@see?com.opensymphony.xwork2.Action#execute()?
  • ?????*/??
  • ????public?String?execute()?throws?Exception?{??
  • ????????//?write?your?logic?here??
  • ????????return?SUCCESS;??
  • ????}??
  • }??


  • 在這個接口定義中,我們可以明顯看到與傳統的MVC框架之間的區別:Struts2中的Action,并不需要依賴于特定的Web容器。我們看不到類似HttpServletRequest,HttpServletResponse等Web容器相關的對象。?

    而這一點,也帶來了問題:?

    提問:Struts2的Action并不帶有任何Web容器相關的對象,Action又是如何工作在Web容器中的呢??

    雖然Struts2的Action只是一個非常普通的Java對象,并不具備任何Web容器的特質,但是我們需要把Action放到一個更加大的環境中來看。事實上,Struts2為Action的執行,準備了完整的數據環境和執行環境。而這個執行環境,就保證了Action在Web容器中的順利運行。?

    在Struts2中,每個Http的請求,會被發送到一個Filter。而這個Filter,就會針對每個請求,創建出一個代碼的執行環境,并在這個基礎上,為每個執行環境配備與之對應的數據環境,這個數據環境中的內容,就來自于Web容器中的一個又一個對象。這樣,就能夠順利調用Action執行代碼而無需擔心它是否運行在Web容器中了。?

    至于這個執行環境和數據環境到底是什么,我們接下來會詳細講到。?

    提問:Struts2的Action并不帶有任何Web容器相關的對象,Action中又如何與Web容器進行通信并獲取Web容器的相關對象呢??

    剛剛我們提到Struts2會為每個Http的請求建立一個執行環境和數據環境。其中,數據環境就成為了Action獲取Web容器的基礎。所以,當Action需要獲取Web容器的相關對象,需要通過數據環境來進行。?


    Struts2的Action的這一個重要特性,至少能為我們帶來以下好處:?

    1. 使得Struts2的Action非常易于測試?

    如果我們完全不考慮Action的執行環境,僅僅把Action看作一個普通的Java對象,那么我們甚至可以直接new一個Action的對象,通過執行其中的方法完成測試。這樣,我們就不需要任何的Mock,來模擬Web容器的環境。?

    2. 結合Action的執行環境,使得Struts2在Control這個層次上,能夠定義更加豐富的執行層次?

    因為Action是一個普通的Java類,而不是一個Servlet類,完全脫離于Web容器,所以我們就能夠更加方便地對Control層進行合理的層次設計,從而抽象出許多公共的邏輯,并將這些邏輯脫離出Action對象本身。事實上,Struts2也正是這么做的,無論是Interceptor,還是Result,其實都是抽象出了Action中公共的邏輯部分,將他們放到了Action的外面,從而更加簡化了Action的開發。?

    3. 使得Struts2的Action看上去更像一個POJO,從而更加易于管理?

    Struts2的Action是一個線程安全的對象。而Web容器傳遞過來的參數,也會傳遞到Action中的成員變量中。這樣,Action看上去就更像一個POJO,從而能夠方便的被許多對象容器進行管理。比如說,你可以非常方便得把Action納入到Spring的容器中進行管理。?

    Action的生命周期?

    接下來,我們再來看看Struts2中的Action的生命周期:?

    ?

    這張圖來自于Struts2的Reference,我們能夠在圖中看到許多我們不熟悉的名詞,比如ActionProxy,Interceptor等等。這些都是Struts2的Control層的重要元素,也是Struts2的Control層的一個層次化的體現。?

    上面的這張圖基本上能夠概括了Struts2的整個生命周期。接下來,我們就對Action中的一些重要元素進行簡單的描述。?

    Action的五大元素?

    在大概了解了Struts2的Action后,我們來重點研究一下在Struts2的Action周圍,為Action進行服務的一些重要元素,這些元素將涵蓋Action的數據環境,Action的執行環境、Action的調度者、Action的層次結構和Action的執行結果。?

    ActionContext —— 數據環境?

    之前我們提到了Struts2的Action并不是一個Servlet,它是脫離了Web容器的。但是對于一個Web框架來說,所有的數據請求(Request)和數據返回(Response)都來源于Web容器,那么Action在執行的時候,如何去獲取這些數據呢??

    這個問題的答案就在于,我們需要為每個Action準備一個數據環境,這個數據環境被稱之為:ActionContext。由于Action是應對于一個又一個的URL請求,所以ActionContext應該具備以下的特性:?

    1. ActionContext應成為Action與Web容器之間的橋梁?

    2. ActionContext中應該保存有針對某個請求的詳細信息?

    3. ActionContext應該是一個線程安全的類對象?

    Interceptor —— 豐富的層次結構?

    簡單回顧一下上面所提到的Action的職責,我們看到,需要在Action這個層面上完成的事情還不少。而完成這些職責,就需要我們對這些職責進行合理的分類和排序,將他們組織成有序的執行隊列。在Struts2中,使用了一種類似責任鏈的設計模式對這些不同的職責進行分類并串聯起來,從而使得Action層具備了豐富的層次結構。而在這個執行隊列中的每個元素,就被我們稱之為Interceptor,也就是攔截器。?

    Struts2 Reference 寫道 Interceptors can execute code before and after an Action is invoked.



    攔截器是AOP中的概念,它本身是一段代碼,可以通過定義“織入點”,來指定攔截器的代碼在“織入點”的前后執行,從而起到攔截的作用。正如上面Struts2的Reference中講述的,Struts2的Interceptor,其攔截的對象是Action代碼,可以定義在Action代碼之前或者之后執行攔截器的代碼。?

    如果仔細留意一下Action LifeCycle圖中的Interceptor和Action的部分,我們可以看到,Interceptor一層一層的把Action包了起來。這是一個典型的堆棧結構,在代碼執行的時候,每個Interceptor不僅需要文成它自身的邏輯,還通過遞歸調用負責下一個攔截器或Action的調用。?

    Struts2 Reference 寫道 Most of the framework's core functionality is implemented as Interceptors. Features like double-submit guards, type conversion, object population, validation, file upload, page preparation, and more, are all implemented with the help of Interceptors. Each and every Interceptor is pluggable, so you can decide exactly which features an Action needs to support.



    也正如Struts2的Reference所說,Struts2提供的絕大多數的功能支持,都通過Interceptor來實現,這些Interceptor可以隨意進行配置,并且能夠方便的插入到程序中去運行。?

    Result —— 執行結果?

    有執行就必然有執行的結果。在Struts2中,Action的執行結果被抽象成了一個層次。在這個層次中,可以定義任意類型的View層的結構。也就是說,Struts2并不強制View層的表現形式,可以是JSP、Freemarker模板、二進制流輸出等等。?

    Struts2把執行結果抽象成一個層次,使得你可以不再關注許多視圖整合上面的細節,只需要考慮視圖的類型和數據的準備,這樣,你也可以不必在沉浸在雜亂的構造視圖的代碼中。?

    ActionProxy —— 執行環境?

    有了攔截器Interceptor,有了Action本身,也有了Action的執行結果Result,我們就需要一個類似調度器的產品,將這些元素整合起來,進行調度執行。在上面的Action Lifecyle的圖中,我們可以看到,Interceptor、Action和Result都處于ActionProxy中,所以ActionProxy就成為了所有這些元素的執行環境。?


    既然是執行環境,那么ActionProxy就需要提供Action執行的時候一切所需要的配置、參數等等,當然,也要有進行Action調用的入口。所以讓我們來看一下ActionProxy的接口:?

    Java代碼??
  • public?interface?ActionProxy?{??
  • ??
  • ????/**?
  • ?????*?Called?after?all?dependencies?are?set?
  • ?????*/??
  • ????void?prepare()?throws?Exception;??
  • ??????
  • ????/**?
  • ?????*?@return?the?Action?instance?for?this?Proxy?
  • ?????*/??
  • ????Object?getAction();??
  • ??
  • ????/**?
  • ?????*?@return?the?alias?name?this?ActionProxy?is?mapped?to?
  • ?????*/??
  • ????String?getActionName();??
  • ??
  • ????/**?
  • ?????*?@return?the?ActionConfig?this?ActionProxy?is?built?from?
  • ?????*/??
  • ????ActionConfig?getConfig();??
  • ??
  • ????/**?
  • ?????*?Sets?whether?this?ActionProxy?should?also?execute?the?Result?after?executing?the?Action?
  • ?????*?
  • ?????*?@param?executeResult?
  • ?????*/??
  • ????void?setExecuteResult(boolean?executeResult);??
  • ??
  • ????/**?
  • ?????*?@return?the?status?of?whether?the?ActionProxy?is?set?to?execute?the?Result?after?the?Action?is?executed?
  • ?????*/??
  • ????boolean?getExecuteResult();??
  • ??
  • ????/**?
  • ?????*?@return?the?ActionInvocation?associated?with?this?ActionProxy?
  • ?????*/??
  • ????ActionInvocation?getInvocation();??
  • ??
  • ????/**?
  • ?????*?@return?the?namespace?the?ActionConfig?for?this?ActionProxy?is?mapped?to?
  • ?????*/??
  • ????String?getNamespace();??
  • ??
  • ????/**?
  • ?????*?Execute?this?ActionProxy.?This?will?set?the?ActionContext?from?the?ActionInvocation?into?the?ActionContext?
  • ?????*?ThreadLocal?before?invoking?the?ActionInvocation,?then?set?the?old?ActionContext?back?into?the?ThreadLocal.?
  • ?????*?
  • ?????*?@return?the?result?code?returned?from?executing?the?ActionInvocation?
  • ?????*?@throws?Exception?
  • ?????*?@see?ActionInvocation?
  • ?????*/??
  • ????String?execute()?throws?Exception;??
  • ??
  • ????/**?
  • ?????*?Sets?the?method?to?execute?for?the?action?invocation.?If?no?method?is?specified,?the?method?provided?by?
  • ?????*?in?the?action's?configuration?will?be?used.?
  • ?????*?
  • ?????*?@param?method?the?string?name?of?the?method?to?invoke?
  • ?????*/??
  • ????void?setMethod(String?method);??
  • ??
  • ????/**?
  • ?????*?Returns?the?method?to?execute,?or?null?if?no?method?has?been?specified?(meaning?"execute"?will?be?invoked)?
  • ?????*/??
  • ????String?getMethod();??
  • ??????
  • }??


  • 很顯然,在這其中,prepare和execute方法是用作Action調用的入口函數,其他的接口定義都與Action執行時的運行參數和配置有關。?

    ActionInvocation —— 調度者?

    在上面的ActionProxy的接口定義中,我們可以看到有一個比較特殊的變量:ActionInvocation比較吸引我們的眼球。從字面上去理解,ActionInvocation就是Action的調用者。事實上也是如此,ActionInvocation在這個Action的執行過程中,負責Interceptor、Action和Result等一系列元素的調度。?

    在之后的章節中,這個ActionInvocation類也將成為我們解讀Struts2源碼的一個重要入手點。這個類將告訴你,Struts2是如何通過ActionInvocation來實現對Interceptor、Action和Result的合理調度的。



    原文鏈接:[http://wely.iteye.com/blog/2295296]

    總結

    以上是生活随笔為你收集整理的Struts2中的Action的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。