在實際的J2EE項目中,系統內部難免會出現一些異常,就如Struts+Spring+Hibernate項目:通常一個頁面請求到達后臺以后,首先是到action(就是MVC中的controller),在action層會調用業務邏輯層service,而在service層會調用持久層dao進而獲得數據,再將獲得的數據一層一層返回到action層,然后通過action控制層轉發到指定頁面,而這期間都可能會發生異常,dao層可能會發生SQLException異常,service層可能會發生NullPointException異常,action層可能會發生IOException異常,如果這三層都不處理的話異常信息會拋到服務器,然后服務器會把異常信息打印到瀏覽器上(用戶看不懂信息,體驗十分不好,),處理得好可以使開發效率快速提升。
通常處理這些異常有兩種方法:①直接throws,②try...catch...在catch塊中不做任何處理,或者僅僅printStackTrace()把異常信息打印出來。第一種就是會在瀏覽器上打印出用戶看不懂的異常信息,第二種方法則是頁面不報錯也不執行用戶的請求。
如何更好的解決這些異常?
首先,在action類、service類、dao類,如果有必要就try...catch...,catch塊內不記錄log,通常是拋出一個新異常
//action層執行數據添加操作
public String save(){try{//調用service的save方法service.save(obj);}catch(Exception e){//拋出Runtime異常可使得不必再方法后寫throws xxthrow new RuntimeException("添加數據時發生錯誤!",e);}return "success";
}
然后在異常攔截器對異常進行處理
public String intercept(ActionInvocation actioninvocation) {String result = null; // Action的返回值try {// 運行被攔截的Action,期間如果發生異常會被catch住result = actioninvocation.invoke();return result;} catch (Exception e) {/*** 處理異常*/String errorMsg = "未知錯誤!";//通過instanceof判斷到底是什么異常類型if (e instanceof BaseException) {BaseException be = (BaseException) e;be.printStackTrace(); //開發時打印異常信息,方便調試if(be.getMessage()!=null||Constants.BLANK.equals(be.getMessage().trim())){//獲得錯誤信息errorMsg = be.getMessage().trim();}} else if(e instanceof RuntimeException){//未知的運行時異常RuntimeException re = (RuntimeException)e;re.printStackTrace();} else{//未知的嚴重異常e.printStackTrace();}//把自定義錯誤信息HttpServletRequest request = (HttpServletRequest) actioninvocation.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);/*** 發送錯誤消息到頁面*/request.setAttribute("errorMsg", errorMsg);/*** log4j記錄日志*/Log log = LogFactory.getLog(actioninvocation.getAction().getClass());if (e.getCause() != null){log.error(errorMsg, e);}else{log.error(errorMsg, e);}return "error";}// ...end of catch}
需要注意的是,在使用instanceOf判斷異常類型的時候一定要從子到父依次找,比如BaseException繼承RunTimeException,則必須首先判斷是否是 BaseException再判斷是RunTimeException,最后在error jsp頁面顯示出具體的錯誤信息
<body>
<s:if test="%{#request.errorMsg==null}"><p>對不起,系統發生了未知的錯誤</p>
</s:if>
<s:else><p>${requestScope.errorMsg}</p>
</s:else>
</body>
以上方式可以攔截后臺代碼所有的異常,但如果出現數據庫鏈接時異常不能被捕捉的則可使用struts2的全局異常處理機制處理
<global-results><result name="error" >/Web/common/page/error.jsp</result>
</global-results><global-exception-mappings><exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>
文章轉自:http://my.oschina.net/u/817908/blog/158056
其他關于J2EE項目異常處理機制請看:http://www.iteye.com/topic/1073599