SpringMVC通过HandlerExceptionResolver处理程序的异常,包括Handler映射、数据绑定以及目标方法执行发生的异常。
SpringMVC提供的HandlerExceptionResolver的实现类
DispatcherServlet默认装配的HandlerExceptionResolver
没有配置mvc:annotation-driven/
配置了则
在实际开发中都会配置mvc:annotation-driven/,所以一般都是使用ExceptionHandlerExceptionResolver。
主要用于处理Handler中用@ExceptionHandler注解定义的方法。
@ExceptionHandler注解的方法优先级问题:例如发生的是NullPointerException,但是生命的异常有RuntimeException和Exception,此时会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler注解方法,即标记了RuntimeException的方法。
ExceptionHandlerMethodResolver内部若找不到@ExceptionHandler注解的话,会找@ControllerAdvice中的@ExceptionHandler注解方法。
//方法中的Exception参数,对应发生的异常对象
@ExceptionHandler(ArithmeticException.class)
public String execException(Exception ex) {
ex.printStackTrace();
return "error";
}
@RequestMapping("/testException")
public String testException(@RequestParam("i") int i) {
//此处如果i是0则会发生异常,默认情况下不会处理,使用@ExceptionHandler注解定义的方法会自动捕获相应的异常
System.out.println(10/i);
return SUCCESS;
}
上述代码只是在Java代码中,如果需要在页面上显示异常信息,则需要另外处理。在@ExceptionHandler修饰的方法中不能传入Map,若希望将异常传入到页面上,需要使用ModelAndView作为返回值。
@ExceptionHandler(ArithmeticException.class)
public ModelAndView execException(Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
return mv;
}
异常处理优先级:
如果在定义了多个异常处理方法,会匹配精确度更高的异常方法,如下定义了两个异常处理方法,一个是匹配RuntimeException,一个是匹配ArithmeticException,前面代码出异常最先匹配的是ArithmeticException修饰的异常方法。
@ExceptionHandler(RuntimeException.class)
public ModelAndView execException(Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
return mv;
}
@ExceptionHandler(ArithmeticException.class)
public ModelAndView execException2(Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
return mv;
}
上述异常处理都是在单个Handler中,其他的Handler是无法匹配到该Handler中的异常方法,可以定义一个类,使用@ControllerAdvice,作为异常处理的公共类,异常方法定义与在单个Handler中定义没有区别。如果在单个Handler中也定义了,同时也定义了@ControllerAdvice标记的类,同时定义了异常方法,那么会先在单个Handler中匹配,如果没有匹配上则会去@ControllerAdvice标记的类去匹配异常方法。
ResponseStatusExceptionResolver
在异常及异常父类中找到@ResponseStatus注解,然后使用这个注解的属性进行处理。
定义一个@ResponseStatus注解修饰的异常类
若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver不解析上述异常。由于触发的异常UnauthorizedException带有@ResponseStatus注解。因此会被ResponseStatusExceptionResolver解析到,最后相应HttpStatus.UNAUTHORIZED代码给客户端。
SimpleMappingExceptionResolver
如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常