J2EE項目中統一異常處理
一. 說明
Spring+ Spring MVC + hibernate項目比較流行,在MVC三層結構中不可避免會有異常出現,若對於每個過程中的異常進行單獨處理,那麼代碼的耦合度太高,不便於維護,所以必然需要解耦,分離出來,因此就出現了異常統一處理這一說法。
Spring MVC處理異常的方式大致有三種:
1.使用Spring MVC提供的簡單異常處理SimpleMappingExceptionResolver
2.實現Spring的異常處理接口HandlerExceptionResolver自定義自己的異常處理器
3.使用@ExceptionHandler註解實現異常處理
以下主要說明第二種處理方式。
二. 自定義異常處理器
先需要新建一個類(名叫ExceptionHandler)實現HandlerExceptionResolver的接口中resolveException方法:
public ModelAndViewresolveException
(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)
在這裏可以直接獲取到異常 ex,爲了更好的處理異常後返回提示信息,我們通過對異常類進行匹配:
if(ex.getClass().equals(NullPointerException.class)
然後向modelAndView寫入相關信息:
StringBuffer errormsg = new StringBuffer(“調用了未經初始化的對象或者是不存在的對象”);
modelAndView.addObject("ex",new Exception(errormsg+""));
最後重定向至錯誤頁面即可看到錯誤信息:
modelAndView.setViewName("exception/error");
但是僅僅如此是不行的,因爲有的時候提示信息範圍太大:
如:添加的字段過長導致報錯,通過ex.getMessage()獲取到的信息爲->
錯誤原因:org.hibernate.exception.GenericJDBCException:could not execute statement]
從這裏基本看不出是字段過長導致的,
於是重點來了:通過
Throwable cause =ex.getCause(); 進一步查看導致異常的原因
如上述的異常可以進行如下處理:
通過 if(ex.getClass().equals(PersistenceException.class))
將異常歸類爲 PersistenceException異常,再通過cause.getClass()對異常再進行細分:
If(cause.getClass().equals(GenericJDBCException.class))
最後通過:
((org.hibernate.exception.GenericJDBCException)cause).getSQLException().getMessage()
獲取異常的原因:會發現爲:
[錯誤原因:ORA-12899: 列 "SCOTT"."STUDENT"."NAME" 的值太大 (實際值: 102, 最大值: 5)]
三. 讓spring 管理到自定義的異常類
在spring mvc的配置文件中加入:
<bean id="exceptionResolver"class="com.nuohy.utils.exception.ExceptionHandler"/>
即可
四. 補充 !!! 獲取最終導致異常的原因:
/**
* 獲取具體信息
* @param cause
* @return
*/
public String getExCause(Exception ex){
String recontent = null;
/**
* 針對處理大部分數據庫異常
*/
Throwable oldcause = ex.getCause();
if(oldcause==null){
recontent = ex.getMessage();
}else{
while(true){
Throwable cau = oldcause.getCause();
if(cau==null){
if(oldcause.getMessage()==null){
recontent = ex.getMessage();
break;
}else{
recontent = oldcause.getMessage();
break;
}
}else{
oldcause = oldcause.getCause();
}
}
}
if(recontent==null){
String errormsg = ex.getMessage();
if(ex.getClass().equals(DataAccessException.class)){
recontent = "發生DataAccessException異常";
}else if(ex.getClass().equals(NullPointerException.class)){
recontent = "調用了未經初始化的對象或者是不存在的對象";
}else if(ex.getClass().equals(IOException.class)){
recontent = "IO異常";
}else if(ex.getClass().equals(ClassNotFoundException.class)){
recontent = "指定的類不存在";
}else if(ex.getClass().equals(ArithmeticException.class)){
recontent = "數學運算異常";
}else if(ex.getClass().equals(ArrayIndexOutOfBoundsException.class)){
recontent = "數組下標越界";
}else if(ex.getClass().equals(IllegalArgumentException.class)){
recontent = "方法的參數錯誤";
}else if(ex.getClass().equals(ClassCastException.class)){
recontent = "類型強制轉換錯誤";
}else if(ex.getClass().equals(SecurityException.class)){
recontent = "違背了安全原則";
}else if(ex.getClass().equals(SQLException.class)){
recontent = "操作數據庫異常";
}else if(ex.getClass().equals(NoSuchMethodError.class)){
recontent = "方法末找到異常";
}else if(ex.getClass().equals(InternalError.class)){
recontent = "Java虛擬機發生了內部錯誤,[錯誤信息:" + ex.getMessage() + "]";
}else if(ex.getClass().equals(UnauthorizedException.class)){
recontent = "您尚未擁有權限訪問該資源,[錯誤信息:" + ex.getMessage() + "]";
}else{
recontent = "未知錯誤!";
}
recontent += errormsg!=null?",[錯誤原因:" + errormsg + "]":"";
}
return recontent;
}
附上源碼下載地址:http://download.csdn.net/detail/qq_27063119/9732953