不同於Struts 1的ActionServlet,Struts 2 採用Filter攔截器作為核心控制器:
<!-- web.xml 核心配置 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
*.action或無後綴請求,靜態資源放行<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 常量配置 -->
<constant name="struts.devMode" value="true" /> <!-- 開發模式:熱加載、詳細錯誤 -->
<constant name="struts.ui.theme" value="simple" /> <!-- UI主題 -->
<constant name="struts.action.extension" value="action,"/> <!-- 支持.action和無後綴 -->
<!-- 包配置:Action分組,支持繼承 -->
<package name="default" namespace="/" extends="struts-default">
<!-- Action定義 -->
<action name="hello" class="com.example.HelloAction" method="execute">
<!-- 結果映射:邏輯視圖名 → 物理資源 -->
<result name="success">/hello.jsp</result>
<result name="input">/error.jsp</result>
<result name="json" type="json"> <!-- JSON結果類型 -->
<param name="root">data</param>
</result>
</action>
<!-- 通配符映射:/user/* -> UserAction.{1} -->
<action name="user/*" class="com.example.UserAction" method="{1}">
<result name="list">/user/list.jsp</result>
<result name="edit">/user/edit.jsp</result>
</action>
</package>
<!-- 模塊化配置:包含子配置文件 -->
<include file="struts-admin.xml"/>
<include file="struts-api.xml"/>
</struts>
| 元素/屬性 | 作用 | 關鍵點 |
|---|---|---|
<package> name | 包唯一標識 | 其他包可通過extends繼承其攔截器/結果類型定義 |
<package> namespace | 命名空間/URL前綴 | 默認"";/admin 對應 URL /admin/actionName |
<package> extends | 繼承基礎包 | 通常繼承struts-default (定義默認攔截器棧、結果類型) |
<action> name | Action訪問路徑 | 支持通配符*、正則{field:regex} |
<action> class | Action實現類全限定名 | Spring管理時可用beanId (需Struts2-Spring插件) |
<action> method | 調用方法名 | 默認execute;支持!method排除、*通配 |
<result> name | 邏輯結果名 | 對應Action返回字符串;默認success |
<result> type | 結果類型 | 默認dispatcher (JSP轉發);redirect/redirectAction/json/stream/freemarker |
<result> param | 結果類型參數 | 如json類型的root指定序列化對象 |
package com.example;
import com.opensymphony.xwork2.ActionSupport; // 提供validate、i18n、錯誤處理
import java.util.Date;
public class HelloAction extends ActionSupport {
// 屬性驅動:自動接收請求參數
private String username;
private int age;
private Date birthDate; // 類型轉換自動處理
// 業務數據:供結果頁面展示
private String message;
private User user;
@Override
public String execute() throws Exception {
// 業務邏輯
if ("admin".equals(username)) {
message = "歡迎管理員 " + username;
user = new User(username, "admin@email.com");
return SUCCESS; // 常量 "success"
} else {
message = "歡迎 " + username;
return INPUT; // "input",對應驗證失敗頁面
}
}
// 手動驗證 (或用XML/註解驗證)
@Override
public void validate() {
if (username == null || username.trim().isEmpty()) {
addFieldError("username", "用戶名不能為空");
}
if (age < 0 || age > 150) {
addFieldError("age", "年齡範圍 0-150");
}
}
// Getter/Setter 省略...
}
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Struts 2 Demo</title></head>
<body>
<h2><s:property value="message" /></h2>
<!-- 表單標簽:自動綁定Action屬性、顯示錯誤 -->
<s:form action="hello">
<s:textfield name="username" label="用戶名" />
<s:textfield name="age" label="年齡" type="number" />
<s:submit value="提交" />
</s:form>
<!-- 迭代顯示 -->
<s:if test="user != null">
<p>用戶: <s:property value="user.username" /> (<s:property value="user.email" />)</p>
</s:if>
<!-- 錯誤顯示 -->
<s:fielderror />
</body>
</html>
URL = ContextPath + Namespace + ActionName + Extension
/myapp/ (package namespace)hello.action 或 無https://localhost:8080/myapp/hello.action 或 /myapp/hello| 現象 | 可能原因 | 解決 |
|---|---|---|
| 404 No result defined | Action返回結果名與<result name>不匹配 | 檢查返回字符串常量 (SUCCESS/ERROR/INPUT/LOGIN/NONE) |
| 無法接收參數 | 屬性名與請求參數名不一致 / 缺少Setter | 確保name="username" 對應 setUsername() |
| 類型轉換失敗 | 日期/數字格式不匹配 | 自定義TypeConverter 或使用@TypeConversion註解 |
| 驗證不生效 | 未繼承ActionSupport / 方法名非validate/validateXxx | 繼承ActionSupport;驗證方法命名規范 |
| 中文亂碼 | 編碼未統一 | web.xml配置CharacterEncodingFilter;JSP/pageEncoding=UTF-8 |
struts-user.xml、struts-order.xml、struts-admin.xml<include file="..."/>引入namespace:/user、/order、/adminstruts-default或自定義base-package中,業務包extends繼承Struts 2 以Filter分發 + POJO Action + 靈活結果映射 + 強大攔截器棧構建MVC框架。掌握struts.xml核心元素(package/action/result/namespace/extends)、Action屬性驅動與驗證、結果類型選擇、模塊化配置,即可快速構建傳統Web應用。雖然Spring MVC已成主流,但理解Struts 2的攔截器鏈、值棧OGNL、類型轉換、插件擴展機制,對掌握Java Web框架設計思想極有裨益。