首先感謝「郡主」對個人支持,她幫忙完善了跳轉地址重定向問題。 java
1. 目標——什麼異常須要咱們處理 web
一般來講,在業務流程中已經將大部分異常進行處理,由於大部分異常是繼承java.lang.Exception,因此開發人員在IDE環境中能夠輕鬆識別並使用try catch語句塊進行處理。可是別忘了java.lang.RuntimeException。struts框架有兩種異常處理方式:action的exception配置和global-exceptions配置 ajax
<action-mappings> <action path="/Test" scope="request" type="com.sg.LoginAction" parameter="method" > <forward name="index" path="/index.jsp"/> <exception key="error.action.message" type="java.lang.RuntimeException"></exception> </action> </action-mappings>
<global-exceptions> <exception key="error.message" type="java.lang.RuntimeException" path="/common/errorPage.jsp" /> </global-exceptions>若LoginAction的方法拋出的RuntimeException(事實上RuntimeException的子類也能夠),struts會嘗試在action配置中查找對應的exception配置並進行處理,若沒有找到,則查找global-exceptions配置並處理,二者都沒有找到,struts框架會拋出ServletException讓web容器處理。
3. 一般的處理思路以及struts框架的弊端
3.1 action的exception和global-exception的選擇
因爲項目中,按模塊、按功能劃分後的action配置會不少,顯然在使用action的exception配置進行同一的RuntimeException處理配置的工做量很是大,global-exceptions是咱們的選擇。
3.2 global-exceptions的配置
RuntimeException的子類很是多,咱們不能把每個RuntimeException的子類都進行配置。還好struts框架對於異常的處理能夠對Exception進行向上轉型並處理,好比Action拋出的NullPointerException,struts會按照NullPointerException->RuntimeException->Exception->Throwable的順序一次查找是否有對應的處理。
3.3 邪惡的struts1框架
1) struts1的global-exeptions是針對配置文件的,假設項目按照功能劃分的struts-user.xml和struts-department.xml,這兩個配置的中的global-exeptions配置是不能共用的。
2) 爲了便於項目組對模塊進行劃分,struts的配置文件一般會設置不一樣的前綴(prefix,最後會有關於prefix的簡單介紹),ActionForward根據前綴的路徑進行跳轉,所以不一樣的struts的配置文件可能須要配置不一樣的跳轉地址。 apache
4. ExceptionHandler帶來的起色
框架的目的之一是爲了讓開發人員忽略技術使用細節,轉而將更多的精力放在業務邏輯實現上。爲了繞開struts的複雜的異常處理,咱們使用struts的ExceptionHandler。
ExceptionHandler是struts默認異常處理類,在Action方法執行發生異常時,ExceptionHander將捕獲異常,並進行更進一步的處理(如將異常根據配置的不一樣放入request或session、配置key國際化等),經過繼承ExceptionHandler,咱們能夠嘗試進行地址的統一跳轉。
struts的跳轉是經過ActionForward的信息進行的,因此在ExceptionHandler子類中創新統一的ActionForward便可,代碼以下:
session
public class CommonExceptionHandler extends ExceptionHandler { private static final Logger logger = Logger.getLogger(CommonExceptionHandler.class); /** 統一跳轉地址路徑 */ private static final String EXCEPTION_PAGE_PATH = "/common/exceptionPage.jsp"; public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.info("統一異常處理 begin"); logger.error("Action拋出了未捕獲的異常", ex); /* * 判斷是否爲ajax請求 * 如果ajax請求,因爲頁面處理方式不一致,不作頁面提示 */ String ajaxFlg = request.getHeader("X-Requested-With"); if(ajaxFlg != null) { logger.info("請求類型爲ajax請求!"); logger.info("統一異常處理 end"); return null; } /* 調用父類方法,方法中會將exception信息放入request */ super.execute(ex, ae, mapping, formInstance, request, response); /* 設置同一跳轉路徑 */ ActionForward forward = new ActionForward("excepationPage", EXCEPTION_PAGE_PATH , false, ""); logger.info("統一異常處理 end"); return forward; } }代碼中有兩處須要注意:
/** * Construct a new instance with the specified values. * * @param name Name of this forward * @param path Path to which control should be forwarded or redirected * @param redirect Should we do a redirect? * @param module Module prefix, if any */ public ActionForward(String name, String path, boolean redirect, String module) { super(); setName(name); setPath(path); setRedirect(redirect); setModule(module); }module指Module prefix,咱們項目在根目錄下的/common/exceptionPage.jsp,因此使用struts-config.xml的prefix,若使用其餘配置文件的prefix須要自行修改。
<servlet> <servlet-name>controller</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value> /WEB-INF/struts/struts-config.xml </param-value> </init-param> <init-param> <param-name>config/page/user</param-name> <param-value> /WEB-INF/struts/config/struts-user.xml </param-value> </init-param> <init-param> <param-name>config/page/user/department</param-name> <param-value> /WEB-INF/struts/config/struts-department.xml </param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet>struts1框架要求param-name必須以config開頭,不然不處理。去掉config/,後面內容就是該配置文件的惟一標識,而這個就是prefix。struts-config.xml比較特別,它的prefix使用空串("")。