Struts2 應用中,未匹配的 URL 默認拋出框架級 404 頁面,體驗差且洩露技術細節。本文提供雙層攔截方案:web.xml 容器級 + struts.xml 框架級,實現友好 404 頁面統一導向。
No result defined for action... 堆疊追蹤。.action 後綴請求優先被 Struts2 攔截,web.xml <error-page> 不生效。<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.html</location>
</error-page>
限制:.action 請求被 Struts2 FilterDispatcher 先攔截,容器層面不觸發 404。
<package name="default" namespace="/" extends="struts-default">
<!-- 關鍵:未匹配任何 action 時導向此 action -->
<default-action-ref name="notFound" />
<action name="notFound">
<result>/404.jsp</result>
</action>
<!-- 其他正常 action -->
<action name="login" class="com.demo.LoginAction">
<result>/welcome.jsp</result>
</action>
</package>
原理:Struts2 找不到匹配 Action 時,自動轉發到 default-action-ref 指定的 Action。
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>頁面不存在</title>
<style>body{font-family:微軟正黑體;text-align:center;padding-top:100px;}</style>
</head>
<body>
<h1>😵 404 - 頁面走失了</h1>
<p>您訪問的頁面不存在或已被移除。</p>
<a href="${pageContext.request.contextPath}/">返回首頁</a>
</body>
</html>
<interceptors>
<interceptor name="notFoundLogger" class="com.demo.NotFoundLoggingInterceptor" />
<interceptor-stack name="defaultStackWithLog">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="notFoundLogger" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStackWithLog" />
public class NotFoundLoggingInterceptor extends AbstractInterceptor {
@Override public String intercept(ActionInvocation invocation) throws Exception {
String actionName = invocation.getProxy().getActionName();
if ("notFound".equals(actionName)) {
log.warn("404 Not Found: URI={}, IP={}, UA={}",
ServletActionContext.getRequest().getRequestURI(),
ServletActionContext.getRequest().getRemoteAddr(),
ServletActionContext.getRequest().getHeader("User-Agent"));
}
return invocation.invoke();
}
}
| 請求類型 | 攔截層級 | 生效配置 |
|---|---|---|
| 靜態資源 (/css/, /js/, /images/) | 容器 (DefaultServlet) | web.xml <error-page> |
| 非 .action 動態請求 | 容器 | web.xml <error-page> |
| .action 但無匹配 Action | Struts2 框架 | struts.xml <default-action-ref> |
| Action 執行拋異常 | Struts2 / 容器 | struts.xml <global-results> + web.xml 500 |
<default-action-ref> 必須在 <package> 內、所有 <action> 之前或之後均可,但建議放在開頭。default-action-ref。<result>/404.jsp</result> 默認 dispatcher 轉發,地址列保持原 URL (友好);若用 redirect 地址列會變成 /404.jsp (不推薦)。雙層防護 (web.xml + struts.xml) 覆蓋所有 404 場景。核心是 Struts2 的 <default-action-ref> 機制,配合友好錯誤頁面與日誌記錄,顯著提升用戶體驗與運維可觀測性。