Struts 2 是基於 WebWork 演進的成熟 MVC 框架,採用攔截器鏈、值棧 OGNL、註解零配置等現代特性。本文涵蓋架構原理、環境搭建、核心組件、約定規則、避坑指南。
| 層 | 組件 | 職責 |
| 控制器 | FilterDispatcher / StrutsPrepareAndExecuteFilter | 攔截請求、調用 Action、結果視圖分發 |
| 模型 | Action (POJO) + 業務服務 + 領域模型 | 封裝請求參數、執行業務邏輯、持有結果數據 |
| 視圖 | JSP / FreeMarker / Velocity / JSON / XSLT | 通過值棧 OGNL 表達式渲染數據 |
環境搭建標準化流程
1. JDK & IDE
- JDK 8/11/17 (LTS 版本),配置 `JAVA_HOME`、`PATH`
- IntelliJ IDEA (推薦) / Eclipse,安裝 Lombok、MyBatis 插件
2. Servlet 容器
# Tomcat 9/10 (Servlet 4.0/5.0)
# 下載解壓 -> bin/startup.sh
# 驗證 https://localhost:8080
# 部署:將 WAR 放入 webapps/ 或配置 Context
3. Maven 依賴 (核心最小集)
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.30</version>
</dependency>
<!-- 註解零配置必需 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.5.30</version>
</dependency>
<!-- JSON 視圖 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.5.30</version>
</dependency>
</dependencies>
4. web.xml 極簡配置 (Servlet 3.0+ 可無)
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value> <!-- 開發模式:熱重載、詳細錯誤 -->
</init-param>
<init-param>
<param-name>struts.convention.action.packages</param-name>
<param-value>com.myapp.action</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
第一個 Action 實戰
@Namespace("/user")
@Action(value="hello", results={
@Result(name="success", location="/hello.jsp"),
@Result(name="input", location="/index.jsp")
})
public class HelloAction extends ActionSupport {
private String name;
public String execute() {
if (name == null || name.trim().isEmpty()) {
addFieldError("name", "姓名不能為空");
return INPUT;
}
return SUCCESS;
}
// Getter/Setter 省略
}
JSP 視圖與標簽庫
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:form action="hello" method="post">
<s:textfield name="name" label="姓名" required="true" />
<s:submit value="提交" />
</s:form>
<!-- 顯示錯誤 -->
<s:fielderror />
<!-- 值棧取值 -->
<s:property value="name" />
<!-- 或 OGNL -->
${name}
核心特性深度解析
1. 值棧
- 線程局部變量 `ActionContext.getContext().getValueStack()`
- 根對象:Action 實例;上下文對象:request、session、application、parameters
- OGNL 表達式:`user.address.city` 自動導航對象圖
2. 攔截器鏈
<!-- struts.xml 定義攔截器棧 -->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/> <!-- 包含 params, validation, workflow 等 -->
<interceptor-ref name="myCustomInterceptor"/>
</interceptor-stack>
<action name="*" class="com.myapp.action.{1}Action" method="{2}">
<interceptor-ref name="myStack"/>
<result>/{1}/{2}.jsp</result>
</action>
3. 類型轉換
- 內建:基本類型、Date、集合、枚舉
- 自定義:實現 `TypeConverter`,註解 `@TypeConversion` 或配置 `xwork-conversion.properties`
4. 驗證框架
- 聲明式:Action 方法註解 (見註解專題)
- 程序式:實現 `Validateable` 接口 `validate()` 方法
- XML:`ActionName-validation.xml` 文件
常見問題避坑指南
| 現象 | 原因 | 解決 |
| 404 無法訪問 Action | Namespace 不匹配、包掃描路徑錯誤 | 檢查 @Namespace、struts.convention.action.packages |
| 參數無法注入 | Setter 缺失、類型轉換失敗、OGNL 表達式錯誤 | 檢查 Getter/Setter、自定義 TypeConverter、devMode 看堆疊 |
| 中文亂碼 | 請求/響應編碼不一致 | Filter 設置 encoding、JSP pageEncoding、Tomcat URIEncoding |
| 驗證不生效 | 未繼承 ActionSupport、workflow 攔截器缺失 | extends ActionSupport、defaultStack 包含 workflow |
| 文件上傳失敗 | multipart 解析器未配置、大小限制 | struts.multipart.maxSize、commons-fileupload 依賴 |
現代化演進建議
- 新項目優先 Spring Boot + Spring MVC:生態更活躍、註解更豐富、響應式支援
- 存量項目:升級 Struts 2.5.x、啟用 Convention Plugin 消除 XML、引入 Jackson 替代舊 JSON 插件
- 安全修補:嚴格升級修復 CVE (S2-0xx 系列 OGNL 注入),禁用動態方法調用 `struts.enable.DynamicMethodInvocation=false`
- 上一篇文章: Java 反射機制核心 API 深度解析與實戰應用模式
- 下一篇文章: Java 驗證碼生成核心流程與實現方案:圖形驗證碼、滑塊驗證、行為分析
Copyright ©
程式碼之家 All Rights Reserved