Struts 2 架構核心:標準 MVC 映射
| MVC 角色 | Struts 2 組件 | 技術實現 |
| Model |
Action + Service + Domain |
POJO Action 直接承載表單數據 (ModelDriven)、業務邏輯委託 Service |
| View |
JSP / FreeMarker / Velocity |
Struts 標簽庫 (`` ``)、OGNL 表達式訪問值棧 |
| Controller |
FilterDispatcher (Struts 2 核心攔截器) |
`struts.xml` 映射 Action、Result、Interceptor Stack |
核心組件詳解
- Action:POJO,無需實現介面,通過 `execute()` 返回結果字符串 (`success`/`error`)。實現 `ModelDriven` 可自動封裝表單到 Domain 物件。
- Interceptor (攔截器):AOP 風格橫切關注點 — params (參數注入)、validation (校驗)、workflow (流程控制)、fileUpload、i18n 等。預設堆疊 `defaultStack` 涵蓋 90% 場景。
- Value Stack (值棧):`OgnlValueStack` 線程局部變量,存放 Action 實例、請求參數、Session/Application 屬性。OGNL 表達式統一訪問 (`user.name`、`#session.token`)。
- Result (結果視圖):`dispatcher` (JSP 轉發)、`redirect` (重定向)、`stream` (文件下載)、`json` (AJAX)、`freemarker` 等。
- 配置文件 `struts.xml`**:Package 繼承 `struts-default`,定義 Action、Result、Interceptor-ref、Global Results/Exception Mappings。
BBS 登入功能實戰 (Struts 2 版)
1. 領域模型
public class User {
private String username, password;
// getter/setter
}
2. Action (ModelDriven 封裝表單)
public class LoginAction extends ActionSupport implements ModelDriven {
private User user = new User();
private UserService userService; // 注入
@Override public User getModel() { return user; }
public String execute() {
if (userService.authenticate(user.getUsername(), user.getPassword())) {
ActionContext.getContext().getSession().put("user", user);
return SUCCESS;
}
addActionError("用戶名或密碼錯誤");
return ERROR;
}
// setter for userService
}
3. struts.xml 配置
/bbs/main.action
/login.jsp
/bbs/main.jsp
4. 登入頁 (login.jsp)
<%@ taglib prefix="s" uri="/struts-tags" %>
5. 主頁
<%@ taglib prefix="s" uri="/struts-tags" %>
歡迎, !
登出
Struts 2 vs Struts 1 vs Spring MVC 關鍵差異
| 維度 | Struts 1 | Struts 2 | Spring MVC |
| Controller | ActionServlet (單例) | FilterDispatcher + Interceptor | DispatcherServlet + HandlerMapping |
| Action 線程模型 | 單例 (需線程安全) | **原型/請求作用域** (天然線程安全) | 單例 (Controller 無狀態) |
| 表單綁定 | ActionForm (單獨類) | **直接屬性驅動 / ModelDriven** | @ModelAttribute / 命令對象 |
| 視圖解析 | JSP 為主 | 多視圖技術 (Result 類型) | ViewResolver 策略模式 |
| 測試性 | 差 (依賴 Servlet API) | 良 (POJO 易 Mock) | 優 (純 POJO、獨立測試) |
避坑指南
- OGNL 表達式注入 (S2-0xx 系列漏洞):升級到 2.5.30+,嚴格限制 `struts.ognl.enableOGNL`、配置 `SecurityMemberAccess`。
- 值棧生命週期**:請求級,重定向會丟失,需用 `redirectAction` 傳參或 Session 存儲。
- 文件上傳大小限制**:`struts.multipart.maxSize` (預設 2MB) + `multi-part` 攔截器。
- 國際化**:`struts.custom.i18n.resources` 全局資源包 + Action 級 `getText()`。
總結
Struts 2 以 **POJO Action + Interceptor Stack + OGNL ValueStack** 重新定義了 Java Web MVC。雖生態漸讓位於 Spring MVC,但大量存量系統仍在運行。掌握其 **攔截器鏈、值棧 OGNL、Result 類型、ModelDriven 綁定** 四大核心,足以應對維護、遷移、二次開發等實戰場景。