第十三章 异常处理
异常处理概述
所有异常解析器尝试解析,解析完成进行后续,解析失败下一个解析器
- Spring MVC 通过 HandlerExceptionResolver【异常解析器】 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。
- SpringMVC 提供的 HandlerExceptionResolver【9大组件之一,有默认的初始化机制 】 的实现类
- 步骤一 获取异常
- 步骤二 会运行下面的方法
- 步骤三 会循环遍历 一个一个找异常处理器
找不到对应的异常处理器 就直接抛出来
HandlerExceptionResolver
DispatcherServlet 默认装配的 HandlerExceptionResolver :
@ExceptionHandler(ArithmeticException.class) public String myerrors(Exception ex) { return "error";//程序异常后 就会转到error页面下 但暂时不能处理将异常信息转发到页面 因为方法只能由一个参数Exception 带model参数就会报错 }
- 如何将异常对象从控制器携带给页面,做异常信息的获取 利用modelAndView 方法类型
@ExceptionHandler(ArithmeticException.class) public ModelAndView myerrors(Exception ex) { ModelAndView modelAndView = new ModelAndView("error"); modelAndView.addObject("ex", ex); return modelAndView; }
匹配异常类型,执行顺序问题
@ExceptionHandler(ArithmeticException.class)//精确优先
@ExceptionHandler(Exception.class)//接收所有异常
- 本类优先于全局 全局的代码
@ControllerAdvice public class errors { @ExceptionHandler(ArithmeticException.class) public ModelAndView myerrors(Exception ex) { ModelAndView modelAndView = new ModelAndView("error"); modelAndView.addObject("ex", ex); return modelAndView; } }
- 本类不精确 全局精确 但是选择本类优先
公共的处理异常的类@ControllerAdvice
ExceptionHandlerExceptionResolver【AnnotationException...通过mvc:annotation注解更改为这个处理解析器】
- 主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
- @ExceptionHandler 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
- ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法
异常处理_ResponseStatusExceptionResolver【自定义异常】
在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
定义一个 @ResponseStatus 注解修饰的异常类
若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver 不解析上述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus 注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码。
@Controller public class MyController { @RequestMapping("/hello") @ResponseStatus(reason= "错误",value = HttpStatus.NOT_EXTENDED) public String getIndex(@RequestParam(value="i",defaultValue = "1") Integer i) { return "hello"; } } 注解不能标在自己的方法上
自定义效果
相对应的控制器代码@Controller public class MyController { @RequestMapping("/hello") public String getIndex(@RequestParam(value = "i", defaultValue = "1") Integer i) { if (i == 0) { System.out.println("请求失败"); throw new IntegerIsZeroException(); } else { System.out.println("请求成功"); return "hello"; } } }
自定义异常的代码
@ResponseStatus(reason="请求参数为0",value = HttpStatus.NOT_ACCEPTABLE) public class IntegerIsZeroException extends RuntimeException{ private static final long serialVersionUID = 1L; }
异常处理_DefaultHandlerExceptionResolver【优先级第三】
判断是否springmvc自带的异常【前面两个没人运行 就交给第三个运行】
通过源码可以知道有很多能够处理的异常
异常处理_SimpleMappingExceptionResolver【优先级最低】
简单映射异常解析器
- 如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
${exception}
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.NullPointerException">error</prop> </props> </property> <!-- 异常信息会放在请求域中 默认是exception 修改为ex--> <property name="exceptionAttribute" value="ex"></property> </bean>
所有的异常最终生成了一个modelAndView 然后页面渲染modelAndView