Struts 2 的 <global-results> 與包繼承(extends)是複用結果配置、減少重複代碼的利器。本文詳細解析全局結果集定義、跨包繼承使用、實戰場景與最佳實踐。
在 <package> 內部定義 <global-results>,包內所有 Action 共享。常用於:
error、403、404)login)mainpage)<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<!-- 定義全局結果集 -->
<global-results>
<result name="mainpage">/main.jsp</result>
<result name="error">/error.jsp</result>
<result name="login" type="redirectAction">LoginAction!input</result>
</global-results>
<action name="index">
<result>/index.jsp</result>
</action>
<action name="user" class="com.example.UserAction">
<result>/user_success.jsp</result>
<result name="error">/user_error.jsp</result> <!-- 覆蓋全局 error -->
</action>
</package>
</struts>
<result>(最高優先級)<global-results><global-results>Action 可通過同名 result 覆蓋全局定義(如上例 error)。
<package name="child" extends="parent"> 繼承父包的:
<global-results>)<interceptor-stack>)<result-types>)<package name="user" namespace="/user" extends="struts-default">
<global-results>
<result name="login" type="redirectAction">LoginAction!input</result>
<result name="error">/common/error.jsp</result>
</global-results>
<!-- 用戶模組 Actions -->
</package>
<package name="admin" namespace="/admin" extends="user">
<!-- 自動擁有 user 包的全局結果集 -->
<action name="admin" class="com.example.AdminAction">
<result>/admin/dashboard.jsp</result>
</action>
</package>
admin 包無需重複定義 login、error,直接複用 user 包配置。
<global-results>
<result name="edit" type="redirectAction">
<param name="actionName">${editAction}</param>
<param name="id">${entityId}</param>
</result>
</global-results>
Action 中提供 getEditAction()、getEntityId() 即可實現動態導向。
<package name="base" extends="struts-default">
<interceptors>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor-stack name="defaultStackWithException">
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">ERROR</param>
</interceptor-ref>
<interceptor-ref name="exception"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStackWithException"/>
<global-results>
<result name="error">/common/system_error.jsp</result>
</global-results>
</package>
所有繼承 base 的包自動獲得異常攔截與統一錯誤頁。
<package name="api" namespace="/api" extends="base">
<!-- API 模組專用配置 -->
</package>
<package name="web" namespace="/web" extends="base">
<!-- Web 模組專用配置 -->
</package>
不同 namespace 避免 Action 名稱衝突,共享基礎設施配置。
| 場景 | 建議方案 |
|---|---|
| 統一錯誤/登入頁 | 基礎包定義 <global-results>,業務包繼承 |
| 模組間共享結果 | 父包定義通用結果,子包 extends 繼承 |
| Action 覆蓋全局結果 | 同名 result 定義在 action 內部 |
| 動態導向參數 | global-results 中使用 ${actionProperty} 表達式 |
| 避免配置膨脹 | 拆分 struts.xml 為模組文件, |
extends="struts-default,json-default" 多重繼承按順序合併,後者覆蓋前者同名定義。<global-results> + 包繼承 = Struts 2 配置複用的核心機制。合理設計包層次(基礎包 → 業務包 → 功能包),將通用結果、攔截器、異常處理下沉到基礎包,業務包專注業務邏輯,實現配置最小化、維護成本最低化。