【Struts2.0】Struts 應用轉移到 Struts 2 (一)

   有很多人都很熟悉 Struts, 無論是從項目中直接獲得的實戰經驗還是從書中瞭解到的。我們這一系列文章,將通過一個由 Stuts 轉移到 Struts2 簡單的例子向大家展現Struts2的所有特徵。
    在我們開始這個例子之前,你需要去知道一點 Struts2的背景知識。在第一部分的文章中,我們將介紹Struts2與Struts的核心框架的不同點,以助於更好地瞭解其他方面的整合。第二部分中,我們將深入探討 actions 的差別, action相關的框架特徵,和action配置。在最後一部分中,我們將會講述 user interface,我們也會講到其架構,UI構件,themes 和標籤。 還有如何爲你的應用加上新的外觀。
    我們並不打算談及遷移過程的所有細節方面,我們只是從出發點開始介紹Struts2 的概念和現在可用的所有特徵。但擁有這些知識,你將在以後Struts2的應用中無往而不利。
   
Struts的歷史
    Struts的第一個版本 是在 2001年5月份發佈。它提供了一個Web應用的解決方案,如何讓 JSPs 和 servlets 共存去提供清晰的分離視圖和業務和應用邏輯的架構。在Struts之前,最通常的做法是在JSP中加入業務和應用邏輯,或者在servlets中生成視圖。
    自從第一個版本的發佈, Struts 實際上已成爲業界公認的Web應用標準。但隨着時間的推移,Web應用框架經常變化的需求,產生了幾個下一代 Struts的解決方案。其中兩個可選方案是Shale 和 Struts Ti。 Shale 是一個基於構建的框架,並在最近成爲 Apache 中的重要項目。而 Struts Ti 則是繼續堅持 MVC模式的基礎上改進,繼續Struts的成功經驗。
    WebWork項目是在2002年3月發佈的,它對Struts式框架進行了革命性改進,引進了不少新的思想,概念和功能,但和原Struts代碼並不兼容。WebWork是一個成熟的框架,經過了好幾次重大的改進與發佈。在2005年12月,WebWork與Struts Ti決定合拼, 再此同時, Struts Ti 改名爲 Struts Action Framework 2.0,成爲Struts真正的下一代。

請求如何運作
    在我們開始詳細探討如何轉移Struts到Struts2之前,讓我們來看看整個請求流程在新架構中是如何運作的。你會注意到在整個請求的生命週期,仍是以controller作主體,而且所有的概念還都是你以前所熟悉的, 就如:

  • 通過URL請求的參數來調用Actions來把數據傳給server.
  • 所有的Servlet objects (request, response, session,之類.) 仍然可以在Action中獲取
下圖展示了整個請求的概要過程:


整個請求過程可以分爲六步驟:
  1. 一個請求產生並經由框架處理 - 框架根據請求匹配相應的配置,如使用哪些攔截器,action 類和結果。
  2. 請求通過一系列的攔截器 - 攔截器,和攔截器組經配置後,能處理不同等級的請求,它們爲請求提供了各種預處理,切面處理。這和Struts的使用 Jakarta Commons Chain 構件的 RequestProcessor類很相似。
  3. 調用 Action - 產生一個新的action對象實例,並提供請求所調用的處理邏輯的方法。Struts2 可以在配置action時爲請求分配其指定的方法。我們在第二部文章中將對這步驟進行進一步討論;
  4. 調用產生的結果 - 獲取通過action的方法處理後返回來的結果,匹配其result class並調用產生的實例。有種情況是在UI模板去生成HTML時纔去處理這些結果。如果在這種情況下,在Struts2 模板中的tags能直接返回到 action 中,取結果來呈現界面。 
  5. 請求再次經過一系列的攔截器處理後返回 - 請求反順序通過與原來進入時的攔截器鏈, 當然,你也可以配置在這個過程中減少或增加攔截器處理.
  6. 請求返回到用戶 - 最後一步是由 control 返回到servlet。通常是生成HTML返回到user, 但你也可以指定返回的HTTP頭或HTTP重定向。
你應該已注意到,Struts2與Struts的差別。最明顯的就是Struts2是pull-MVC 架構,就是可以直接從Action中獲取所需要的數據,而不是像Struts那樣必須把 beans 存到page, request,或者session中才能獲取。這個我們將在下一章中詳細提及。

配置框架
首先最重要的是,讓框架能通過web.xml在servlet containers裏運行。
下面這個就是大家都熟悉的 Struts在 web.xml裏的配置方法
   
  <servlet>
        
<servlet-name>action</servlet-name>
        
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        
<init-param>
            
<param-name>config</param-name>
            
<param-value>/WEB-INF/struts-config.xml</param-value>
        
</init-param>
        
<load-on-startup>2</load-on-startup>
    
</servlet>

    
<servlet-mapping>
        
<servlet-name>action</servlet-name>
        
<url-pattern>*.do</url-pattern>
    
</servlet-mapping>

在 Struts2 中,這個有少許改變,最明顯的是dispatcher 由servlet轉爲servlet filter, 其配置和servlet一樣簡單,如下:
   
 <filter>
         
<filter-name>webwork</filter-name>
           
<filter-class>
            org.apache.struts.action2.dispatcher.FilterDispatcher
   
</filter-class>
    
</filter>

    
<filter-mapping>
   
<filter-name>webwork</filter-name>
   
<url-pattern>/*</url-pattern>
    
</filter-mapping>

和servlet配置一樣,filter配置定義了名稱(供關聯)和filter的類。filter mapping讓URI匹配成功的的請求調用該filter。默認情況下,擴展名爲".action"。
這個是在default.properties文件裏的"struts.action.extension" 屬性定義的。
工具箱:  "default.properties"是配置選項定義文件。通過在classpath中包含一個叫"struts.properties"的文件,並設置不同的屬性值,你可以覆蓋這個默認的配置,實現自己的配置。
對於Struts, servlet配置提供了初始化tag的參數和使用的文件,而Struts2沒有這樣的配置參數,取而代之的是在classpath下的默認配置文件"struts.xml"。
工具箱/提示:  Struts actions(擴展名".do"),Struts2 actions(擴展名".action"),所以Struts和Struts2可以在一個系統中共存。所以最好是保持原先的系統,在新功能的開發上用 Struts2, 如果時間和資源允許的情況下再逐步遷移。另一種方法是隻是把Struts2的擴展名改爲".do",可重用JSPs.
分析Actions
在上面介紹的請求運作流程中,我們談及了一些Struts和Struts2的不同點。現在我們將較深入地探討這兩個框架中action結構的具體差別。
讓我們來回顧一下 Struts 的 action 結構, 主要的形式如下:
public class MyAction extends Action {
    
public ActionForward execute(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
            
throws Exception {
        
// do the work
        return (mapping.findForward("success"));
    }

}

當實現一個Struts action時, 你需要注意一下問題:
  1. 所有的action 都必須繼承於base Action 類.
  2. 所有的action都必須是線程安全的,因爲action是單例的,singleton的.
  3. 因爲所有的action都必須是線程安全的,所以所有的對象都不能是類屬性, 都必須以方法參數的形式傳值。
  4. 調用action的方法必須命名爲 "execute" ( 在Struts中的  DispatchAction 類好像可以用其它方法去執行同一個action ,但實際上在框架中調用的仍然是 "execute" 方法。).
  5. ActionForward 的結果是通過ActionMapping 類中的方法來產生的,通常是"findForward"方法.
相比較之下, Struts2的action 提供了很多簡單的實現。下面就是個例子
public class MyAction {
   
public String execute() throws Exception {
        
// do the work
        return "success";
   }

}

首先你會注意到的是,Struts2中的action不再繼承於任何類或需要實現任何接口。實際上,它還遠不只這些。按照慣例,只有"execute"方法能調用action, 但在Struts2中並非必要,任何聲明爲public String methodName() 方法都能通過配置來調用action.
另外,你會注意到返回值不再是"ActionForward ",而是String, 如果你需喜歡String的形式,那在Action接口裏有個幫助方法可以提供簡單的結果常量,如"success", "none", "error", "input" 和 "login"。
最後,和Struts最大的革命性的不同是, 調用action不再是帶參數的。那你如何在獲得你所需要的值呢?答案是"inversion of control" 或 "dependency injection", 反轉控制(想了解更多可以看Martin Fowler的文章 http://www.martinfowler.com/articles/injection.html)。
爲了更好地瞭解反轉控制,讓我們來看看一個例子,如何在action處理過程中可以訪問到HttpServerRequest 。在我們的例子中,我們用ServletRequestAware 接口,這個接口包含了相應屬性的setter,如下
public interface ServletRequestAware {
    
public void setServletRequest(HttpServletRequest request);
}

當我們繼承這個接口時,我們需要通過setter爲我們的HttpServerRequest 屬性變量賦值:
public class MyAction implements ServletRequestAware {
   
private HttpServletRequest request;
   
public void setServletRequest(HttpServletRequest request) {
        
this.request = request;
   }

   
public String execute() throws Exception {
        
// do the work using the request
        return Action.SUCCESS;
   }

}

看起來現在這些屬性是類級別的,並不是線程安全的,但是在Struts2裏並沒有問題,因爲每個請求過來的時候都會產生一個新的action對象實例,它並沒有和其他請求共享一個對象,所以不需要考慮線程安全問題。

現在我們還有最後一步,就是把action關聯上ServletConfigInterceptor 攔截器。這個攔截器繼承了ServletRequestAware 接口,並提供了把HttpServletRequest 注入到action中的功能。但是你現在不用擔心如何配置這些,我們將在下一篇文章中具體講述。最重要的是我們明白了攔截器和接口共同爲action提供了反轉控制的功能。
這個設計的好處是能讓action完全和框架解耦。action僅僅是一個被框架使用的簡單的POJO。這對於單元測試但來極大的好處,你能方便的爲Struts action實現 StrutsTestCase 或  MockStrutsTestCase 單元測試。

總結
By到現在爲止,你應該已經瞭解了Struts2的整個請求流程,還有高層的框架概念, 你也應該能自己動手配置Struts2的action,和講出Struts和Struts2的差別了。
在下篇文章中,我們將會介紹一個詳細的Struts應用向Struts2遷移的例子,同時我們也會介紹遷移中相關的知識,會講述如何綜合使用JSTL, JSP 和 Struts2,進一步講述Struts和Struts2的action的差別,Struts2的配置和其他框架元素,和談到更多的其他相關框架的特徵。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章