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