Struts 2 並非 Struts 1 的簡單升級,而是融合了 WebWork 精華、重寫核心架構的全新框架。雖然保留了 Struts 的設計思想,但在 Action 模型、線程策略、Servlet 解耦、測試性、數據綁定、表達式語言、類型轉換、驗證、攔截器等十大維度實現了質的飛躍。本文系統梳理這些差異,助力遷移決策與技術選型。
| 維度 | Struts 1 | Struts 2 |
|---|---|---|
| 編程風格 | 抽象類繼承(Action、DispatchAction) | 接口實現(Action)或純 POJO |
| 強制性 | 必須繼承基類 | 可選;任何含 execute() 的類均可 |
| 依賴注入 | 不支持 | 原生支持(Setter/構造器/接口注入) |
影響:Struts 2 Action 更輕量、可測試、易於單元測試與 Spring 整合。
| 場景 | Struts 1 | Struts 2 |
|---|---|---|
| execute 簽名 | execute(mapping, form, request, response) | execute() 無參;需時通過 ServletActionContext 獲取 |
| 單元測試 | 需模擬 Servlet 容器(如 StrutsTestCase) | 直接實例化 Action,注入屬性即可測試 |
| Session 訪問 | 通過 request.getSession() | ActionContext.getContext().getSession()(Map 風格) |
Struts 2 Action 為 POJO,無容器依賴,JUnit 測試極簡:
@Test
public void testLogin() {
LoginAction action = new LoginAction();
action.setUsername("admin");
action.setPassword("123456");
action.setUserService(mockUserService); // 注入 Mock
String result = action.execute();
assertEquals("success", result);
}
ActionForm 的表單 Bean,常導致大量冗余類(DTO↔Form 雙維護)。ActionForm 模式平滑遷移。OGNL 支持:
users[0].nameorder.customer.address.cityuser.getFullName()users.{? #this.age > 18}<jsp:useBean> 或 EL 訪問。ValueStack 作為線程局部棧,攔截器將 Action 壓入棧頂,標籤通過 OGNL 直接訪問棧中對象屬性,無需綁定到作用域,支持同名不同類型屬性的覆蓋與復用。Struts 2 內建常用類型轉換器(基本類型、日期、集合、枚舉等),並支持自定義 TypeConverter 註解或配置文件聲明,實現「一次配置、全局生效」。
| 特性 | Struts 1 | Struts 2 (XWork) |
|---|---|---|
| 聲明式驗證 | XML 配置(Commons Validator) | XML/註解/Action 方法/訪問器模式 |
| 嵌套對象驗證 | 不支持 | 支持(visitor 驗證器遞歸驗證子屬性) |
| 字段級/屬性級 | 僅字段級 | 同時支持 |
| 國際化錯誤消息 | 需手動配置 | 內建 i18n 支持 |
RequestProcessor,所有 Action 共享同一生命週期。Struts1Plugin 兼容舊 Action,可逐模塊遷移。ModelDriven 接口處理複雜表單。struts.xml 或註解中。Struts 2 在保留 Struts MVC 核心思想的基礎上,通過「接口編程、依賴注入、攔截器鏈、OGNL、ValueStack」五大支柱,構建了更靈活、可測試、高性能的 Web 框架。理解這十大差異,不僅是遷移指南,更是掌握現代 Java Web 框架設計精髓的窗口。