Struts 作為經典的 Java Web MVC 框架,雖然歷經 Struts 1 → Struts 2 演進,但其核心設計思想仍深刻影響現代框架。本文以 Struts 2 為主線(兼顧 Struts 1 關鍵差異),從環境搭建、核心組件、配置詳解、實戰範例到優缺點分析與實施經驗,為您提供完整的 Struts 入門與進階指南。
lib/(核心依賴)、apps/(WAR 範例)apps/struts2-showcase.war 複製到 Tomcat/webapps/https://localhost:8080/struts2-showcase/# 目錄結構
my-struts-app/
├── index.jsp
├── WEB-INF/
│ ├── web.xml
│ ├── struts.xml # Struts 2 核心配置
│ ├── classes/ # 編譯後 class
│ └── lib/ # 複製 struts2-core.jar 等依賴
| 組件 | 對應傳統角色 | 核心職責 |
|---|---|---|
| FilterDispatcher (Struts 2 核心過濾器) | ActionServlet | 統一請求入口、生命週期管理、攔截器鏈調度 |
| Action (POJO 動作類) | Servlet 邏輯處理 | 封裝業務流程、持有表單資料、返回結果碼 |
| Interceptor (攔截器) | Servlet 通用邏輯 | 參數封裝、驗證、檔案上傳、國際化、記錄等橫切關注點 |
| Result (結果類型) | RequestDispatcher | 視圖渲染:JSP、FreeMarker、Velocity、JSON、Stream、Redirect |
struts.xml 集中定義所有請求映射、攔截器堆疊、結果視圖,一份檔案掌握全站脈絡,維護升級極具優勢。
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>User Registration</title></head>
<body>
<s:form action="register" theme="simple">
<s:textfield name="username" label="Username" required="true"/>
<s:password name="password" label="Password" required="true"/>
<s:textfield name="email" label="Email" required="true"/>
<s:submit value="Register"/>
</s:form>
</body>
</html>
package com.example.action;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction extends ActionSupport {
// 表單屬性自動注入
private String username;
private String password;
private String email;
// Getter/Setter 省略
@Override
public String execute() {
// 呼叫 Service 層業務邏輯
boolean success = userService.register(username, password, email);
return success ? SUCCESS : ERROR;
}
// 驗證方法(選配)
public void validate() {
if (username != null && username.length() < 3) {
addFieldError("username", "用戶名至少 3 字元");
}
if (email != null && !email.contains("@")) {
addFieldError("email", "Email 格式錯誤");
}
}
}
<struts>
<package name="default" extends="struts-default">
<action name="register" class="com.example.action.RegisterAction">
<result name="success">/success.jsp</result>
<result name="error">/register.jsp</result>
<result name="input">/register.jsp</result> <!-- 驗證失敗返回 -->
</action>
</package>
</struts>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html><body>
<h2>註冊成功!歡迎 <s:property value="username"/></h2>
<p>Email: <s:property value="email"/></p>
</body></html>
<s:property value="username"/> 相當於 action.getUsername()<interceptor-stack name="myStack">
<interceptor-ref name="params"/> <!-- 參數注入 -->
<interceptor-ref name="validation"/> <!-- 驗證 -->
<interceptor-ref name="workflow"/> <!-- 驗證失敗返回 input -->
<interceptor-ref name="fileUpload"/> <!-- 檔案上傳 -->
</interceptor-stack>
dispatcher (預設):JSP 轉發redirect / redirectAction:重導向json:REST API 回傳 JSON(需 struts2-json-plugin)stream:檔案下載freemarker/velocity:模板引擎| 維度 | Struts 1 | Struts 2 |
|---|---|---|
| 核心控制器 | ActionServlet | FilterDispatcher |
| Action 設計 | 繼承 ActionForm/Action 類 | POJO,實作 Action 介面或繼承 ActionSupport |
| 表單資料 | ActionForm 封裝 | Action 直接屬性 + 參數攔截器自動注入 |
| 標籤庫 | 獨立 bean/html/logic 標籤 | 統一 struts 標籤,支援主題/範本 |
| 驗證 | validate() 方法 / XML | validate() / 註解 / XML / 獨立驗證框架整合 |
| 依賴注入 | 無 | 原生支援(Spring 整合無縫) |
| 測試性 | 依賴 Servlet API,難測試 | POJO 易於單元測試 |
struts.xml 一覽全站路由,團隊協作/接手維護極友善struts.xml 膨脹,模組化拆分需規劃<include file="user-struts.xml"/>global.properties 管理Struts 2 以 POJO Action + 攔截器鏈 + 值棧/OGNL + 配置驅動導航 重新定義了 Java Web MVC。雖非新專案首選,但理解其設計精髓——關注點分離、配置集中化、攔截器模組化——對掌握 Spring MVC、WebFlux 等現代框架有極大啟發價值。選擇框架無絕對標準,適合團隊能力、專案周期、維護預期者,即為最佳選擇。