SpringMVC 异常统一处理的三种方式:
- 使用@ExceptionHandler 注解
- 实现 HandlerExceptionResolver 接口
- 使用 @ControllerAdvice注解
总结:
当以下三个方式,一起出现时,只执行范围最小的方式,后面的方式不再执行处理;
执行范围:@ExceptionHandler < @ControllerAdvice + @E..Handler < HandlerExceptionResolver
人话:当某个Mapping发生异常后,先有@ExceptionHandler处理;如果没有上者,则由@ControllerAdvice + @E..Handle 处理;如果没有上者,则由HandlerExceptionResolver 处理
- 使用@ExceptionHandler注解
- 作用域:局部,针对一个Controller中的指定异常类:
- 注有该注解的方法,和发生异常的Mapping方法,两者需要在同一个Controller里面;
1 @RestController 2 public class TestExceptionController { 3 4 @RequestMapping("/testEx01") 5 public Map testEx01(){ 6 Map codeMap = new HashMap(); 7 int i = 9/0; 8 codeMap.put("code",200); 9 codeMap.put("msg","ok"); 10 return codeMap; 11 } 12 // @ExceptionHandler 参数为 要处理器的 异常类(或子类) 13 @ExceptionHandler(ArithmeticException.class) 14 public Map exInfo(ArithmeticException e){ 15 Map codeMap = new HashMap(); 16 System.out.println(e.getMessage()); 17 codeMap.put("code",700); 18 codeMap.put("msg","分母不能为0"); 19 return codeMap; 20 } 21 22 }
- 使用HandlerExceptionResolver 接口(前后端分离项目不使用)
- 作用域:全局,针对全部Controller,无需指定某个异常类;
- HandlerExceptionResolver 接口中,只有resolveException 一个方法,实现即可;
1 //作用域:全局,针对全部Controller,无需指定某个异常类 2 @Component 3 public class HandlerEx implements HandlerExceptionResolver { 4 @Override 5 public ModelAndView resolveException(HttpServletRequest httpServletRequest, 6 HttpServletResponse httpServletResponse, Object o, Exception e) { 7 System.out.println(e.getMessage()); 8 ModelAndView mv = new ModelAndView(); 9 mv.setViewName("/systemException"); 10 return mv; 11 } 12 }
- 使用 @ControllerAdvice 注解(可以用于前后端分离项目,经常使用的)
- 作用域:全局,针对全部 Controller 中的指定异常类;
- 该注解需要 和 @ExceptionHandler 配合,来完成全局异常的处理;
- 注意:两个注解的配合,发生异常 Mapping 方法 与 @ExceptionHandler 注解的方法,就可以不用卸载用一个Controller 里;
1 //统一 异常的通知 2 @RestControllerAdvice //restController 的通知 3 public class ZDYExceptionAdvice { 4 5 @ExceptionHandler(Exception.class) 6 public Map showInfoE(Exception e){ 7 System.out.println(" 统一异常 "); 8 System.out.println(e.getMessage()); 9 10 Map codeMap = new HashMap(); 11 codeMap.put("code",800); 12 codeMap.put("msg","系统繁忙!!"); 13 return codeMap; 14 } 15 16 // @ExceptionHandler 参数为 要处理器的 异常类(或子类) 17 // 注解参数不声明指定异常类,则默认为方法列表中的异常参数类 18 @ExceptionHandler(ArithmeticException.class) 19 public Map showInfo(Exception e){ 20 System.out.println(" 算数异常 "); 21 System.out.println(e.getMessage()); 22 23 Map codeMap = new HashMap(); 24 codeMap.put("code",800); 25 codeMap.put("msg","你不能把分母设置为0"); 26 return codeMap; 27 } 28 29 //自定义 异常 30 @ExceptionHandler(ZDYException.class) 31 public Map zdyException(ZDYException e){ 32 System.out.println(e.getMsg()); 33 34 Map codeMap = new HashMap(); 35 codeMap.put("code",e.getCode()); 36 codeMap.put("msg",e.getMsg()); 37 return codeMap; 38 } 39 }
自定义异常:
1 //测试 自定义异常 2 @RequestMapping("/testEx03") 3 public Map zdyEx(int x,int y){ 4 Map codeMap = new HashMap(); 5 if (y == 0) { 6 throw new ZDYException(1111,"自定义异常"); 7 } 8 int i = x/y; 9 codeMap.put("code",200); 10 codeMap.put("msg","ok"); 11 codeMap.put("data",i); 12 return codeMap; 13 }
需要继承 RuntimeException:
1 //自定义异常 2 public class ZDYException extends RuntimeException{ 3 private int code; 4 private String msg; 5 6 public ZDYException() { 7 } 8 9 public ZDYException(int code, String msg) { 10 this.code = code; 11 this.msg = msg; 12 } 13 14 public int getCode() { 15 return code; 16 } 17 18 public void setCode(int code) { 19 this.code = code; 20 } 21 22 public String getMsg() { 23 return msg; 24 } 25 26 public void setMsg(String msg) { 27 this.msg = msg; 28 } 29 }