前言
大型 Struts2 應用中,不同模塊常出現同名 Action(如各模塊都有 list、save)。Struts2 通過**命名空間**機制隔離 Action 命名空間,配合包配置實現模塊化管理。本文深度解析 namespace 配置規則、URL 映射邏輯、常見誤區及最佳實踐。
一、核心概念
- Package(包):Struts2 配置的基本單元,可繼承
struts-default,定義攔截器棧、結果類型、Action 映射
- Namespace(命名空間):包級別屬性,用於區分不同包下的同名 Action,類似 Java 包名或 URL 路徑前綴
- Action 名稱:包內唯一標識,對應 URL 中
.action 前的部分
二、配置語法與規則
1. 基本配置
<struts>
<!-- 繼承默認包,指定命名空間 /book -->
<package name="bookPackage" namespace="/book" extends="struts-default">
<action name="getBooks" class="cn.ss.GetBookAction" method="execute">
<result name="success">/WEB-INF/jsp/book/list.jsp</result>
</action>
<action name="addBook" class="cn.ss.AddBookAction">
<result name="success">/WEB-INF/jsp/book/form.jsp</result>
</action>
</package>
<!-- 另一模塊,同樣有 list Action 但不衝突 -->
<package name="userPackage" namespace="/user" extends="struts-default">
<action name="list" class="cn.ss.UserListAction">
<result>/WEB-INF/jsp/user/list.jsp</result>
</action>
</package>
</struts>
2. 關鍵規則
| 規則 | 說明 |
| Namespace 僅能定義在 <package> 上 | 不支持直接在 <action> 上指定 namespace |
| 默認命名空間 | 未指定 namespace 時,默認為空字符串 ""(根命名空間) |
| Namespace 必須以 / 開頭 | /book、/admin/user,不能為 book 或 book/ |
| 同一命名空間下 Action 名稱唯一 | 同一 package 內或不同 package 但相同 namespace 下,action name 不能重複 |
| 不同命名空間可有同名 Action | /book/list 和 /user/list 互不干擾 |
三、URL 映射解析邏輯
完整 URL 結構
https://host:port/contextPath/namespace/actionName.action
// 示例
https://localhost:8080/myapp/book/getBooks.action
// 解析:contextPath=/myapp, namespace=/book, actionName=getBooks
特殊情況處理
| Namespace 配置 | 訪問 URL | 備註 |
namespace="/book" | /book/getBooks.action | 標準情況 |
namespace="" (默認) | /getBooks.action | 根命名空間,無前綴 |
namespace="/" | /getBooks.action | 等同於根命名空間 |
Action 配置 name="" | /book/.action | 不推薦,語義不清 |
四、進階應用:模塊化項目結構
推薦的包劃分策略
struts.xml (主配置,僅引入模塊配置)
├── struts-book.xml (namespace="/book")
├── struts-user.xml (namespace="/user")
├── struts-order.xml (namespace="/order")
├── struts-admin.xml (namespace="/admin")
└── struts-common.xml (namespace="", 通用 Action)
主配置文件引入
<struts>
<include file="struts-book.xml"/>
<include file="struts-user.xml"/>
<include file="struts-order.xml"/>
<include file="struts-admin.xml"/>
<include file="struts-common.xml"/>
</struts>
模塊配置示例 (struts-book.xml)
<!DOCTYPE struts PUBLIC ...>
<struts>
<package name="book" namespace="/book" extends="struts-default">
<action name="*" class="cn.book.{1}Action" method="{2}">
<result name="success">/WEB-INF/jsp/book/{1}_{2}.jsp</result>
<result name="input">/WEB-INF/jsp/book/{1}_form.jsp</result>
</action>
</package>
</struts>
使用通配符映射 {1}、{2} 進一步簡化配置,實現 REST 風格 URL:/book/list.action、/book/save.action 自動映射到 ListAction.list()、SaveAction.save()。
五、常見問題與排查
| 現象 | 可能原因 | 解決方案 |
| 404 Not Found | Namespace 拼寫錯誤(大小寫、漏 /) | 檢查 struts.xml namespace 與 URL 完全一致 |
| Action 映射不到 | 多個包同名 Action 且 Namespace 相同 | 確保 Namespace 唯一,或合併到同一包 |
| 通配符映射失效 | struts.enable.DynamicMethodInvocation 為 false | 設置 <constant name="struts.enable.DynamicMethodInvocation" value="true"/> |
| Session 淨失效 | 跨 Namespace 重定向攔截器棧不同 | 統一繼承基礎包,確保攔截器棧一致 |
六、最佳實踐總結
- 按業務模塊劃分 Package + Namespace:一個模塊一個包,Namespace 與模塊名一致(如
/order、/payment)
- 統一繼承基礎包:定義
basePackage 含通用攔截器、結果類型,各模塊包 extends="basePackage"
- 善用通配符映射:減少重複 Action 配置,配合 REST 風格命名
- 根命名空間僅放置通用 Action:如登錄、首頁、錯誤頁,業務 Action 全部進入具體 Namespace
- 配置文件模塊化拆分:使用
<include> 組裝,避免單文件過大