例外處理


Struts框架提供每一個 Action 物件處理自己例外的方法,只要使用<exception>標籤在struts-config.xml中定義,例如:
...
 <action
    path="/LoginAction"
    type="onlyfun.caterpillar.LoginAction"
    name="userForm"
    input="/login.jsp">
    <exception
        key="login.failure"
        path="failure.jsp"
        type="onlyfun.caterpillar.LoginFailureException"/>
    <forward
        name="greeting"
        path="/greeting.jsp"/>
...

key屬性的設定是用來匹配訊息資源檔中的value值,如果在Action物件丟出type所指定的例外,將轉送至path 屬性所指定的頁面,與例外相關的訊息會被封裝在ActionErrors物件中,您可以在failure.jsp中使用<html: messages>來顯示相關的錯誤訊息。

除了為每一個Action物件指定例外的處理,您也可以定義一個全局可匹配的例外,使用<global-exceptions>標籤來進行聲明:
...
    <global-exceptions>
        <exception
            key="expired.password"
            type="onlyfun.caterpillar.ExpiredPasswordException"
            path="/changePassword.jsp"/>
    </global-exceptions>
 ...

如果您想要深入瞭解Struts的例外處理方式,可以看看RequestProcessor原始碼中的processException()方法,以及 ExceptionHandler的execute()方法。

當Action物件丟出例外時,RequestProcessor的processException()方法會看看是否有在< exception>標籤中聲明,這個工作是委由ActionMapping物件的findException()方法來執行,如果找不到相對應的 例外處理,除了標籤中聲明,這個工作是委由ActionMapping物件的findException()方法來執行,如果找不到相對應的例外處理,除 了IOException直接丟出之外,其它的例外則將之包裝為ServletException例外再丟出:
ExceptionConfig config =
          mapping.findException(exception.getClass());
 
if(config == null) {
    ....
 
    if(exception instanceof IOException) {
        throws (IOException) exception;
    }
    else if(exception instanceof ServletException) {
        throws (ServletException) exception;
    }
    else {
        throws new ServletException(exception);
    }
}
 

如果RequestProcessor的processException()找到對應的例外處理,則載入ExceptionHandler進行處理,最後返回一個ActionForward物件:
Class handlerClass = Class.forName(config.getHandler());
ExceptionHandler handler =
           (ExceptionHandler) handlerClass.newInstance();
return (handler.execute(exception, config,
                                            mapping, form,
                                            request, response));