基於struts1.框架的異常處理方案

首先感謝「郡主」對個人支持,她幫忙完善了跳轉地址重定向問題。 java

1. 目標——什麼異常須要咱們處理 web

    一般來講,在業務流程中已經將大部分異常進行處理,由於大部分異常是繼承java.lang.Exception,因此開發人員在IDE環境中能夠輕鬆識別並使用try catch語句塊進行處理。可是別忘了java.lang.RuntimeException。
    有不少常見的異常,如java.lang.NullPointerException、java.lang.IndexOutOfBoundsException,都是RuntimeException的子類,這類異常在IDE開發環境中不易判斷,並且常常會致使意外的結果,這些異常正式是本文要處理的東西。
    PS:不要小看java.lang.NullPointerException,在作單元測試的過程當中,一半以上的失敗結果都是它形成的,相信在每個項目中它都是一個可怕的存在。

2. struts1框架對異常的處理支持

    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;
	}
}
    代碼中有兩處須要注意:
    1) ajax請求能夠處理(代碼中之因此沒有處理是由於咱們項目的ajax請求處理不統一,所以不能統一設置,有待Ajax處理方案統一),但不能使用統一的跳轉,由於跳轉後response中設置的跳轉頁面的代碼,ajax請求結果處理方法不須要這些信息;
    2) ActionForward的構造方法有4個參數:
/**
     * 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須要自行修改。
    
關於prefix
    struts的每個配置文件都有惟一標識,這個標識在web.xml中配置struts文件時指定,如
<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使用空串("")。
相關文章
相關標籤/搜索