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"/>
...
<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>
...
<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);
}
}
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));
ExceptionHandler handler =
(ExceptionHandler) handlerClass.newInstance();
return (handler.execute(exception, config,
mapping, form,
request, response));