springmvc全局异常
- 实现步骤
- 在web层下新建一个类
- 通过实现spring的HandlerExceptionResolver接口来捕获所有的异常。
- 写一个异常处理类实现HandlerExceptionResolver接口
如下:
public class MvcWholeExceptionResolver implements HandlerExceptionResolver
{
private static final Logger logger = Logger.getLogger(MvcWholeExceptionResolver.class);
//mvc捕获异常
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception exception)
{
//可以在mv里放异常的页面地址和异常的信息
ModelAndView mv=new ModelAndView();
if(exception!=null)
{
//自定义封装的业务异常抛出类
BizException bizException = null;
logger.warn("MVC全局异常捕捉类捕捉到异常");
if(exception instanceof LoginException)
{
logger.warn("捕捉到业务异常子类登录异常抛出类:LoginException");
bizException=(BizException)exception;
}}else{ logger.warn("捕捉到系统未知异常:UNCLASSFY_EXCEPTION"); logger.warn("UNCLASSFY_EXCEPTION: "+exception); bizException=BizException.UNCLASSFY_EXCEPTION; //要捕捉更多业务类的异常,在自定义更多像LoginException的子类即可,或者在建立像BizException一样的类,这里就举这两个例子,其它仿照拓展 } logger.warn("异常代码:"+bizException.getCode()+" 异常信息:"+bizException.getMessage()); //如果前端是通过ajax请求的后台抛出异常,那么无需返回异常页面,只需要返回异常信息,方法如下: //在request作用域里保存异常的代码和信息 request.setAttribute(UsualConstants.RETURN_ERROR_CODE_KEY, bizException.getCode()); request.setAttribute(UsualConstants.RETURN_ERROR_MSG_KEY, bizException.getMessage()); //在通过转发到controller里的方法,返回@ResponsBody方式,前台ajax里自然会捕捉到,如下: try{ logger.warn("转发到ajax的统一异常处理方法"); request.getRequestDispatcher("/manage/login/jsonException").forward(request, response); }catch(Exception e){ logger.warn("转发到ajax统一异常处理出错"); e.printStackTrace(); } } //虽然ajax的异常在前面已经返回给前端了,但是还会执行到这里,如果在mv里没有加任何东西或者只加异常信息,return时会报错,但不影响前端,前端已经捕捉到ajax的异常了 //如果在mv里有加入跳转的异常页面,那么前端也会跳转,根据具体需要要不要跳转具体异常页面,这里不放具体页面 mv.addObject(UsualConstants.RETURN_ERROR_MSG_KEY,bizException.getMessage()); return mv; }
- 在springMVC的配置文件中要指定全局异常处理类的位置,如下:
- ajax的统一异常处理方法,如下:
@RequestMapping("jsonException")
@ResponseBody
public ResultJson jsonException(HttpServletRequest request,Map map)
{
logger.warn("统一异常处理方法,取出异常代码和异常信息封装到ResultJson,方法通过@ResponseBody方式返回ResultJson,前台得到信息为json格式");
Integer errorCode=(Integer)request.getAttribute(UsualConstants.RETURN_ERROR_CODE_KEY);
String errorMsg=(String)request.getAttribute(UsualConstants.RETURN_ERROR_MSG_KEY);
ResultJson rj=new ResultJson();
rj.setKey(errorCode);
rj.setMessage(errorMsg);
logger.warn("返回的ResultJson对象为:"+rj);
return rj;
}
- 在springMVC的配置文件中要指定全局异常处理类的位置,如下:
在service层或者dao层里,自定义统一业务异常抛出类,如下:
package cn.hj.yzp_app1.common.tools.exception;
import cn.hj.yzp_app1.common.tools.constantsTools.StatusConstants;
//业务异常基类,所有业务异常都必须继承于此异常
public class BizException extends RuntimeExceptionAware
{
//RuntimeExceptionAware是自定义的运行时异常类,下面例子会贴出代码
private static final long serialVersionUID = -697081422076812812L;
//定义系统未知异常
public static final BizException UNCLASSFY_EXCEPTION = new BizException(StatusConstants.UNCLASSFY_EXCEPTION_CODE, StatusConstants.UNCLASSFY_EXCEPTION_MSG);
}//异常编号 protected int code; //异常信息 protected String msg; //实例化异常 public BizException newInstance(String message, Object... args) { return new BizException(this.code, message, args); } public BizException(int code, String message, Object... args) { //父级变量 super(message); this.code = code; this.msg = String.format(message, args); } public BizException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public BizException(String message) { super(message); // TODO Auto-generated constructor stub } public BizException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } public BizException() { super(); // TODO Auto-generated constructor stub } /** * @return the code */ public int getCode() { return code; } /** * @param code the code to set */ public void setCode(int code) { this.code = code; } /** * @return the msg */ public String getMsg() { return msg; } /** * @param msg the msg to set */ public void setMsg(String msg) { this.msg = msg; } /** * @return the serialversionuid */ public static long getSerialversionuid() { return serialVersionUID; }
运行时异常处理类
package cn.hj.yzp_app1.common.tools.exception;
public class RuntimeExceptionAware extends RuntimeException{
//RuntimeException是系统的运行时异常类
private static final long serialVersionUID = -4896922247366620859L;
}public RuntimeExceptionAware() { super(); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(String message) { super(message); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(Throwable cause) { super(cause); // TODO Auto-generated constructor stub }
自定义的登录异常抛出类:LoginException,如下:
package cn.hj.yzp_app1.common.tools.exception;
import org.apache.log4j.Logger;
import cn.hj.yzp_app1.common.tools.exception.BizException;
//自定义登录异常
public class LoginException extends BizException{
//属于业务异常BizException的子类
private static final long serialVersionUID = -6160637178050783184L;
private static final Logger logger = Logger.getLogger(LoginException.class);
public LoginException() {
super();
// TODO Auto-generated constructor stub
}
}public LoginException(int code, String message, Object... args) { super(code, message, args); // TODO Auto-generated constructor stub } public LoginException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public LoginException(String message) { super(message); // TODO Auto-generated constructor stub } public LoginException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub }
抛出异常例子,如下:
@RequestMapping("loginVerify")
@ResponseBody
public ResultJson loginVerify(UserExtend user,HttpSession session) {
ResultJson rj=new ResultJson();
try{
userServiceImpl.login(user);
}catch(NullPointerException e){
//如登录操作时,捕获到空指针异常了,就可以认为是登录异常,抛出后在MvcWholeExceptionResolver里就可以捕捉到,然后在返回前端提示给用户
throw new LoginException(StatusConstants.NO_LOGINMSG_CODE,StatusConstants.NO_LOGINMSG_MSG);
}
}