Struts 的異常處理機制帶來極大便利。經思考與實作,採用以下方式較靈活:
先定義基底類別(可為抽象類),繼承 RuntimeException,以便在 Struts Action 中順利捕捉:
public class BaseException extends RuntimeException { ... }
再定義子類別:DAO 異常、事務處理異常、Service 異常等。Spring 的 org.springframework.dao 定義了一套 DAO 異常,值得參考。
<global-exceptions>
<exception key="todo" type="org.chage.exception.BaseException"
handler="org.chage.exception.MyExceptionHandler" />
</global-exceptions>
此處 key 屬性暫不使用。
package org.chage.exception;
import org.apache.struts.action.ExceptionHandler;
import ...
public class MyExceptionHandler extends ExceptionHandler {
public ActionForward execute(
Exception exception,
ExceptionConfig config,
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws ServletException {
request.setAttribute("exception", exception);
// 返回原始請求的 Forward,或可定義全域異常 Forward
return mapping.getInputForward();
}
}
在頁面(設為發生異常 Action 的 input 屬性)使用 Struts 標籤顯示:
<logic:present name="exception">
<bean:write name="exception"/>
</logic:present>
此處顯示的訊息與資源屬性檔無關,為自行拋出的異常訊息。
傳統做法在 Action 中 try-catch 邏輯錯誤(如用戶名重複、資料被刪),產生 ActionErrors 轉向錯誤頁。但設計良好的 Action 應只是 Web 層的「路標指引器」,真正邏輯委託業務 Bean。採用全域異常機制,Action 無需處理邏輯異常,由業務 Bean 拋出,Struts 捕獲處理,減少 Action 中 try-catch 區塊,繞開 ActionError,思路更清晰。異常在發生處拋出,向上傳遞至 Action,Struts 負責捕獲(前提是異常已定義)。
若不想寫處理器,struts-config.xml 中 handler 屬性也要移除。在 JSP 頁面引用 JSTL 標籤庫後可這樣顯示:
<c:out value="${requestScope['org.apache.struts.action.EXCEPTION'].message}"/>