Struts 2 並非 Struts 1 的簡單升級,而是吸收 WebWork 核心架構後的重生產物。雖名稱僅加「2」,但底層已完成從「抽象類繼承」到「接口編程」、從「單例 Action」到「請求級實例」的範式轉移。
| # | 維度 | Struts 1 | Struts 2 | 影響 |
|---|---|---|---|---|
| 1 | Action 類結構 | 強制繼承抽象類 Action/DispatchAction |
任意 POJO,可選實現 Action 接口或繼承 ActionSupport |
Struts 2 解耦框架依賴,利於單元測試與多重繼承 |
| 2 | 線程模型 | 單例模式,線程不安全,開發者需手動同步 | 請求級實例,天然線程安全 | Struts 2 消除併發 Bug 溫床,降低心智負擔 |
| 3 | Servlet API 依賴 | execute() 參數強綁 HttpServletRequest/Response |
Action 脫離容器,可通過 Aware 接口按需注入 |
Struts 2 支持脫容器測試,集成 Spring 更自然 |
| 4 | 可測試性 | 依賴容器,需 Cactus 等容器內測試框架 | 純 POJO,JUnit 直接 new 實例注入屬性即可測試 | Struts 2 大幅降低測試成本,推動 TDD |
| 5 | 輸入捕獲 | 專用 ActionForm,需繼承基類,導致大量樣板類 |
Action 屬性直接接收,支持巢狀對象圖,兼容 ActionForm 模式 | Struts 2 消除 Form Bean 膨脹,表單綁定更靈活 |
| 6 | 表達式語言 | 僅 JSTL EL,集合/索引屬性支持弱 | 內建 OGNL,支持投影、選擇、Lambda 表達式 | Struts 2 視圖層表達力質變,複雜數據渲染極簡 |
| 7 | 值綁定機制 | JSP page/request/session/application 作用域綁定 |
ValueStack(值棧),切面式訪問,同名不同類型屬性自動區分 | Struts 2 頁面復用率高,標籤庫無需綁定特定 Bean |
| 8 | 類型轉換 | Commons-BeanUtils,全局轉換器不可配置 |
OGNL 內建轉換器,支持自定義 TypeConverter 精確到屬性級 |
Struts 2 類型轉換更精準,日期/枚舉/集合零配置 |
| 9 | 驗證框架 | validate() + Commons Validator,不支持子對象鏈式驗證 |
XWork 驗證框架,支持 visitor 驗證子屬性、字段級錯誤消息 |
Struts 2 驗證更細粒度,國際化錯誤消息開箱即用 |
| 10 | Action 生命周期控制 | 模塊級 RequestProcessor,所有 Action 共享 |
攔截器棧,每 Action 可定製專屬攔截器鏈 | Struts 2 横切關注點(權限、日誌、事務)組合靈活 |
| 遷移動機 | 建議 |
|---|---|
| 新項目啟動 | 直接上 Struts 2 或 Spring MVC |
| 存量 Struts 1 系統穩定運行 | 不強制遷移,新增模塊可獨立用 Struts 2 共存 |
| 頻繁遇到線程安全/測試困難 | 優先遷移核心高併發模塊 |
| 需引入 REST/JSON/AJAX 密集交互 | Struts 2 內建 REST 插件與 JSON 結果類型優勢明顯 |
Struts 1 是「重框架、輕業務」的繼承體系;Struts 2 是「輕框架、重業務」的組合體系。
實際開發中,Action 類的差異(POJO vs 繼承、請求實例 vs 單例)衍生出測試、併發、擴展的全鏈路優勢,這正是 Struts 2 成為經典的根本原因。