绝大多数情况下,其实程序对于exception并没有自我解决的能力,一般情况对于exception都进行2个操作:1、日志记录,2、给予友好的界面提示,并返回错误信息
针对这一特点,在一般情况下,在dao、service、action层,均不作异常捕获,一律抛出。
在action层抛出异常之后,使用springmvc框架中的HandlerExceptionResolver对异常进行全局性处理
定义一个类,实现org.springframework.web.servlet.HandlerExceptionResolver接口
在这个类中对AJAX请求和非AJAX请求分别进行处理
package com.fhzz.core.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import com.fhzz.core.utils.HTTPUtils;
/**
* @author YangYi
*
* 统一的全局异常处理,当controller层抛出异常时,由此类统一处理
*/
@Component
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
Log logger = LogFactory.getLog(CustomHandlerExceptionResolver.class);
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object object,
Exception exception) {
logger.error(exception.getMessage(), exception);// 异常日志记录
// 判断是否AJAX请求
if (!HTTPUtils.isAjaxRequest(request)) {// 如果不是AJAX请求,VM格式返回
ModelAndView modelAndView = new ModelAndView("error/errorInfoPage"); // 统一跳转到errorPage页面
modelAndView.addObject("success", false);
modelAndView.addObject("errorMsg", exception.getMessage());
return modelAndView;
} else {// 如果是AJAX请求,JSON格式返回
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("success", false);
modelAndView.addObject("errorMsg", exception.getMessage());
return modelAndView;
}
}
}
1、如果界面跳转的请求,则统一跳转到errorPage界面,并将错误信息显示于界面上
在界面上使用$errorMsg即可获得错误信息
$(function() {
// 首先备份下jquery的ajax方法
var _ajax = $.ajax;
// 重写jquery的ajax方法
$.ajax = function(opt) {
// 备份opt中error和success方法
var fn = {
error : function(XMLHttpRequest, textStatus, errorThrown) {
},
success : function(data, textStatus) {
}
}
if (opt.error) {
fn.error = opt.error;
}
if (opt.success) {
fn.success = opt.success;
}
// 扩展增强处理
var _opt = $.extend(opt, {
error : function(XMLHttpRequest, textStatus, errorThrown) {
switch (XMLHttpRequest.status) {
case 400:
// 未授权异常
alert("请求无效");
break;
case 403:
// 未授权异常
alert("您没有访问权限");
break;
case 404:
alert("您访问的资源不存在");
break;
case 500:
alert("内部服务器错误");
break;
}
// 打印responseText,方便排查问题
console.log(XMLHttpRequest.responseText);
// 错误方法增强处理
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success : function(data, textStatus) {
if (data.sessionInvalid) {
// 跳转到登录页面,这里要加上top.为了防止在iframe界面中弹出了登录界面
top.location.href = 'toLogin.do?message=' + data.message;
return;
}
if (!textStatus) {
showMsg(data.errorMsg, "操作失败,错误信息", 0, 200, 400);
} else if (typeof (data.success) != 'undefined'
&& !data.success) {
showMsg(data.errorMsg, "操作失败,错误信息", 0, 200, 400);
} else {
fn.success(data, textStatus);// 成功回调方法增强处理
}
},
beforeSend : function(XHR) {
// 提交前回调方法,全局统一的等待提示框
// 例如$('body').append("正在加载,请稍后...");
},
complete : function(XHR, TS) {
// 请求完成后回调函数 (请求成功或失败之后均调用)。
// 取消全局统一的等待提示框,例如//$("#ajaxInfo").remove();
}
});
return _ajax(_opt);
};
});
此处一并加入了403,404错误的返回信息,这类错误会直接进入error方法内
返回403错误的方法具体参考Spring-securtiy相关内容中的CustomAccessDeniedHandler
所以使用
而本文中的CustomHandlerExceptionResolver 返回的信息会进入success方法
有其中的success 设置为了false,errorMsg为exception.getMessage() ,这里可以根据实际情况进行更如何用户需要的展示
if (!textStatus) {
showMsg(data.errorMsg, "操作失败,错误信息", 0, 200, 400);
} else if (typeof (data.success) != 'undefined' && !data.success) {
showMsg(data.errorMsg, "操作失败,错误信息", 0, 200, 400);
} else {
fn.success(data, textStatus);// 成功回调方法增强处理
}
可以在界面进行统一处理
那么action就可以完全专注于正常逻辑的处理,而异常直接交由了框架负责