March 7, 2008

Struts1與Struts2的比較

Struts1 v.s Struts2

作為最受歡迎的Web frameworkStruts擁有眾多的優點,如實踐MVC2 model、功能齊全的Tag LibraryOpen Source等。但隨著Web AP的發展及應用越來越多元,Struts1也有不少的缺點讓使用者詬病,如Unit test困難及容易造成class過多等問題,進而衍生出了Struts2


做為Struts1缺點的解決方案,Struts2Struts1主要區別如下:


一、Action Class

Action是整個Struts1 framework的核心內容, Struts2也不例外。不過兩者的Action model有著很大的區別。其中的關鍵在於Struts2是一個pull-MVC架構。這代表了需要顯示給使用者的資料可以直接從Action中取得,而不用和Struts1一般,需把相對應的Bean物件存到PageRequest或者SessionScope中才能獲取。

進一步說明,在Struts1中,Action必須繼承org.apache.struts.action.Action或其子類別,並將Form表單參數封裝在FormBean中。然而在Struts2中,Action無須繼承任何class或實現任何interfaceForm表單參數可直接包含在Action中,透過getset的方法取得。

(可參考下面的Struts2Action.java sample)

ps:雖然,在理論上Struts2Action無須實現任何接口或者是繼承任何的類,不過在實際coding的過程中,為了更加方便的實現Action,大多數情況下還是會繼承com.opensymphony.xwork2.ActionSupport類,並且覆寫(Override)此類裡的String execute()方法。


Struts2Action.java

package com.demo.action;

import com.opensymphony.xwork2.ActionSupport;

public class Struts2Action extends ActionSupport {

private String message;

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

@Override

public String execute() throws Exception {

System.out.println(message);

return SUCCESS;

}
}

Struts2Action.java可看出,return的對象不是ActionForward,而是String。此外,在com.opensymphony.xwork2.Action interface中以定義常用屬性方式提供結果,如「success」、「none」、「error」、「input」和「login」等。

另外,按照慣例,在Struts1中只有「execute」方法能呼叫Action, 但在Struts2中並非必要,任何聲明為public String methodName() 方法,都能通過配置struts.xml來呼叫Action

最後,和Struts1最大革命性的不同是,Struts2處理Action過程中呼叫的方法execute()是不帶參數的,而是利用IoC(反轉控制)的方式獲取所需參數。


二、反轉控制 IoC(Inversion of Control)

亦稱為依賴注入(Dependency Injection)模式,Spring framework使得這個模式流行起來,然而Struts2的前身WebWork也同時應用上了這個模式。

想更瞭解IoC相關資訊的請參考這篇Martin Fowler的文章

Inversion of Control Containers and the Dependency Injection pattern


三、攔截器(Interceptor)

攔截是AOP(Aspect-Oriented Programming)的一種實現策略。而攔截器是動態攔截Action呼叫的對象。它提供了一種機制可以使開發者定義在一個action執行的前後執行的程式碼,也可以在一個action執行前阻止其執行。同時也提供了一種可以提取action中可重用的部分的方式。

Struts1的標準框架中不提供任何形式的攔截器,雖有一個名為SAIFplug in實現了類似的功能,但它適用的範圍還很有限。

攔截器是Struts2的一個強有力的工具,有許多功能都是基建於它之上,如國際化、轉換器,驗證等。Struts 2已經提供各式功能齊全的攔截器實現。可到struts-default.xml查看關於默認的攔截器配置。

Struts2不僅在Action方面做出改變,還加強了對AOPIoC的支持,而這些特性在Struts1中是很難想像的。至此不難瞭解, Struts2WebWork的升級,而不是Struts1的升級。雖然Struts 2提供了與Struts1的兼容,但已經不是Struts1的升級。


結論

因此對於已有Struts1開發經驗的開發者而言,Struts1的開發經驗對於Struts2並沒有太大的幫助;相反,對於已經有WebWork開發經驗的開發者而言,WebWork的開發經驗對Struts2的開發將是一個很好的借鏡。


Struts1與Struts2整體比較整理如下表


特性

Struts1

Struts2

Action

Action classes

要求Action類要繼承一個抽象類別(abstract)Struts1.x的問題在於使用一個abstract類別取代使用interfaces

Action可以實作一個Action interface,也可實現其他自定義的interfaces提供服務。Struts2提供一個基本的ActionSupport class去實現常用的interfaces。然而Action interface並不是必要的,任何有execute方法POJO class都可以作為Struts2Action

線程模型

Threading Model

Struts1 Action是單例模式並且必須是線程安全的,因為僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能作的事,並且要在開發時特別小心。Action資源必須是線程安全的或同步的。

Struts2 Action對象為每一個請求產生一個實例,因此沒有線程安全問題。(實際上,servlet容器給每個請求產生許多可丟棄的對象,並且不會導致性能和垃圾回收問題)

Servlet 依賴

Servlet Dependency

Struts1 Action 依賴於Servlet API ,因為當一個Action被調用時HttpServletRequest HttpServletResponse 被傳遞給execute方法。

Struts 2 Action不依賴於容器,允許Action脫離容器單獨被測試。倘使需要,Struts2 Action仍然可以訪問初始的requestresponse。但是,其他的元素減少或者消除了直接訪問HttpServetRequest HttpServletResponse的必要性。

易測性

Testability

測試Struts1 Action的一個主要問題是execute方法依賴servlet API,這使得測試過程需綁定於容器。或是透過第三方進行測試,如Struts TestCase提供了一套Struts1的模擬對象來進行測試。

Struts 2 Action可以通過初始化、設置屬性、調用方法來測試,「依賴注入」支持也使測試更容易。

截取輸入

Harvesting Input

Struts1 使用ActionForm對象捕獲輸入。所有的ActionForm必須繼承一個基類。因為其他JavaBean不能用作ActionForm,開發者經 常創建多餘的類捕獲輸入。動態BeanDynaBeans)可以作為創建傳統ActionForm的選擇,但是,開發者可能是在重新描述(創建)已經存在的JavaBean,仍然會導致有冗餘的JavaBean

Struts 2直接使用Action屬性作為輸入屬性,消除了對第二個輸入對象的需求。輸入屬性可能是有自己()屬性的rich對象類型。Action屬性能夠通過web頁面上的taglibs訪問。Struts2也支持ActionForm模式。rich對象類型,包括業務對象,能夠用作輸入/輸出對象。這種ModelDriven 特性簡化了taglibPOJO輸入對象的引用。

表達式語言

Expression Language

Struts1 整合了JSTL,因此使用JSTL EL。這種EL有基本對象圖遍歷,但是對集合和索引屬性的支持很弱。

Struts2可以使用JSTL,但是也支持一個更強大和靈活的表達式語言--"Object Graph Notation Language" (OGNL).

將值綁定到頁面

Binding values into views

Struts 1使用標準JSP機制把對象綁定到頁面中來訪問。

Struts 2 使用ValueStack技術,使taglib能夠訪問值而不需要把你的頁面(view)和對象綁定起來。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重用頁面(view)。

類型轉換

Type Conversion

Struts 1 ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進行類型轉換。每個類一個轉換器,對每一個實例來說是不可配置的。

Struts2 使用OGNL進行類型轉換。提供基本和常用對象的轉換器。

驗證

Validation

Struts 1支持在ActionFormvalidate方法中手動校驗,或者通過Commons Validator的擴展來校驗。同一個類可以有不同的校驗內容,但不能校驗子對象。

Struts2支持通過validate方法和XWork校驗框架來進行校驗。XWork校驗框架使用為屬性類類型定義的校驗和內容校驗,來支持chain校驗子屬性

Action執行控制

Control Of Action Execution

Struts1支持每一個模塊有單獨的Request Processors(生命週期),但是模塊中的所有Action必須共享相同的生命週期。

Struts2支持通過Interceptor Stacks為每一個Action創建不同的生命週期。Stacks能夠根據需要和不同的Action一起使用。


其他相關參考可參閱

Comparing the Struts 1 and Struts 2 Web Application Frameworks

Struts1 vs Struts2


0 comments :