@ExceptionHandler注解
HandlerExceptionResolver接口以及SimpleMappingExceptionResolver解析器类的实现使得你能声明式地将异常映射到特定的视图上,还可以在异常被转发(forward)到对应的视图前使用Java代码做些判断和逻辑。但是在一些场景,特别是依靠@ResponseBody返回响应而非依赖视图解析机制的场景下,直接设置响应的状态码并将客户端需要的错误信息直接写回响应体中,可能是更方便的方法,同时可以实现声明式的将异常映射到特定的视图上。
局部异常处理
我们使用这个@ExceptionHandler注解时,首先我们需要定义一个异常的处理方法,比如上面的handleExeption()方法,给这个方法加上@ExceptionHandler注解,这个方法就会处理类中其被@RequestMapping注解控制器抛出的异常。
@Controller
@RequestMapping("/exec2")
public class Exception2Controller {
@RequestMapping("exceptionHand2")
@ResponseBody
public CommonResult exceptionHandDemo(@RequestParam int num) throws Exception {
if(num==2){
throw new Exception("num can not equal 2");
}
return new CommonResult(0,"sucess");
}
@ExceptionHandler(Exception.class)
@ResponseBody
public CommonResult handlerException(Exception e){
System.out.println(e.getMessage());
return new CommonResult(1,"false",e.getMessage());
}
}
当num=2时则会抛出"num can not equal 2"的异常,则会被@ExceptionHandler进行拦截,并进入异常处理方法,并进行返回的统一处理。
1.注解的参数,可以是某个异常具体类,则只处理这种异常。
2.就近原则,当异常有多个类进行拦截的时候,采用就近原则。比如之前提到的NumberFormatException,这个异常有父类RuntimeException,RuntimeException还有父类Exception,如果我们分别定义异常处理方法。则会触发就近的RuntimeException.
3.注解方法的返回值。标识了@ExceptionHandler注解的方法,返回值类型和标识了@RequestMapping的方法是统一的,可参见@RequestMapping的说明,比如默认返回Spring的ModelAndView对象,也可以返回String,这时的String是ModelAndView的路径,而不是字符串本身。
全局异常处理
可以将@ExceptionHandler方法定义在@ControllerAdvice类中,那么它会处理相关控制器中抛出的异常。@ControllerAdvice 可以通过指定扫描的包的路径或者指定注解或者指定class,来实现范围的圈定。
@ControllerAdvice
public class ControllerException {
@ExceptionHandler(Exception.class)
public CommonResult handlerException(Exception e){
System.out.println(e.getMessage());
return new CommonResult(1,"false",e.getMessage());
}
}
未显式指定@ControllerAdvice 范围则默认对当前类路径下的控制器有作用,从而可以实现控制器的异常的全局处理。