Spring MVC 异常处理有两种方法:
一、使用@ExceptionHandler标识处理异常的方法(不推荐)
在需要做异常处理的类中写一个方法,方法用@ExceptionHandler标识,当这个类中有方法发生异常时,@ExceptionHandler标识的方法就会捕获到该异常,进而对其进行处理,如下:
/**
* @ExceptionHandler 捕获当前类的异常
* ({Exception.class}) 指定捕获特定的异常
* Exception e :捕获到的异常对象
* ModelAndView:给异常页面传递数据,必须使用它,其他的不行(至少model和map不行)。
* @ExceptionHandler 捕获异常是有优先级的,距离指定异常越近,就执行那一个方法
*/
@ExceptionHandler({Exception.class})
public ModelAndView test(Exception e){
System.out.println("出现异常了,异常是:" + e);
ModelAndView mav = new ModelAndView("error");
mav.addObject("e",e);
return mav;
}
@ResponseBody
@ExceptionHandler({NumberFormatException.class})
public String test2(Exception e){
System.out.println("【出现异常了,异常是】:" + e);
return "出现异常了";
}
//文章列表页面
@RequestMapping("/list/page")
public String listPage(){
int a = Integer.parseInt("a");
return "admin/content/admin-blog-content-list";
}
当请求listPage()方法时,如果出现异常,异常就会被上面两个@ExceptionHandler标识的方法捕获到,这里有两个方法,那么该执行哪一个呢?这个就涉及到捕获异常的优先级了。
发生异常时,如果当前类有多个@ExceptionHandler标识的方法,那么那个方法越接近异常,那么就执行那个方法。
二、使用@ControllerAdvice定义全局异常(推荐)
使用第一种方法时,如果有多个类都要使用捕获异常,那么没有类都要使用@ExceptionHandler标识方法,太麻烦了。
现在直接通过@ControllerAdvice定义一个全局的捕获异常的类,所有的类出现异常都会被@ControllerAdvice定义的类所捕获。
/**
* 全局异常
*/
@ControllerAdvice //定义全局异常,异常集中处理,更好的使业务逻辑与异常处理剥离开
public class CommExceptionHandler {
@ResponseBody
@ExceptionHandler(value = {Exception.class})//统一处理某一类异常,从而能够减少代码重复率和复杂度
public Msg handler(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException {
if(e instanceof ClientException) { //客户端异常(自定义异常)
ClientException clientException = (ClientException) e;
return clientException.getMsg();
}else if(e instanceof MsgException) { //后台异常(自定义异常)
MsgException msgException = (MsgException) e;
return msgException.getMsg();
}else if(e instanceof BindException) {//参数绑定校验异常
BindException bindException = (BindException) e;
if (bindException.hasErrors()) {
return new Msg(bindException.getAllErrors().get(0).getDefaultMessage());
}
}
e.printStackTrace();
//系统其它的异常 全部统一返回
return new Msg("系统服务开小差了,请稍后再试");
}
}
用@ControllerAdvice定义的类中,也要写@ExceptionHandler标识的方法,出现异常时,就会执行@ExceptionHandler标识的方法。
1、方法出现异常时,@ExceptionHandler标记的方法的执行顺序
1)当一个类里面的方法出现异常时:先在该方法所在的类中找有没有@ExceptionHandler标记的方法,如果有,执行它
2)如果在当前类里面没有,就全局搜索看看有没有@ControllerAdvice标记的类,如果有,就执行该类里面@ExceptionHandler标记的方法。
2、自定义异常的创建
继承RuntimeException 就可以了,如:
public class ClientException extends RuntimeException {
private Msg msg;
public ClientException(Msg msg) {
super(msg.getMsg());
this.msg = msg;
}
public Msg getMsg() {
return msg;
}
public void setMsg(Msg msg) {
this.msg = msg;
}
}
3、手动抛出自定义异常:
throw new ClientException(null);