一. 异常处理分析
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息, 后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端 控制器交由异常处理器进行异常处理,如下图:
Spring MVC处理异常有3种方式:
(1)使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
(2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
(3)使用@ExceptionHandler注解实现异常处理;
下面分别介绍着3种异常处理.并分析他们的特点
二. Spring自带的简单异常处理器SimpleMappingExceptionResolver
springmvc中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,使用非常简单,直接在springmvc.xml配置就好了
<!--配置简单异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--配置默认的错误视图-->
<property name="defaultErrorView" value="error"/>
<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
<property name="exceptionAttribute" value="ex"></property>
<!--配置异常和视图的映射-->
<property name="exceptionMappings">
<map>
<!--类转换异常,显示视图error页面-->
<entry key="java.lang.ClassCastException" value="error"/>
<!--空指针异常,显示视图error页面-->
<entry key="java.lang.NullPointerException" value="error"/>
<!--还可以配置自定义的其他异常...-->
</map>
</property>
</bean>
使用SimpleMappingExceptionResolver进行异常处理,具有集成简单、有良好的扩展性(可以任意增加自定义的异常和异常显示页面)、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。
三. 自定义异常处理器
springmvc提供一个HandlerExceptionResolver接口,自定义全局异常处理器必须要实现这个接口,该接口只有一个方法. 自定义全局异常处理器处理思路:
- 解析出异常类型
- 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
- 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//打印堆栈信息
e.printStackTrace();
MyExpection ex=null;
ModelAndView modelAndView = new ModelAndView();
if (e instanceof MaxUploadSizeExceededException){
//系统的中异常可以直接转换
ex=(MyExpection)e
}else{
//如果抛出的不是系统自定义的异常则重新构造一个未知错误异常
ex = new MyExpection("其他异常....");
}
modelAndView.addObject("errorMessage",ex.getMessage());
modelAndView.setViewName("error");
return modelAndView ;
}
}
之后还需要把自定义的异常处理器,注册到Spring容器中,也就是在spring配置文件中加上以下内容
<!--自定义异常处理器-->
<bean class="com.zuoyueer.exception.MyExceptionHandler"/>
从上面的集成过程可知,使用实现HandlerExceptionResolver接口的异常处理器进行异常处理,具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。
四. 使用@ExceptionHandler注解实现异常处理
建议使用 @ControllerAdvice+ @ ExceptionHandler注解,如果单独使用@ ExceptionHandler注解,那么控制器类要继承BaseController类,
通过 @ControllerAdvice 注解,我们可以在一个地方对所有 @Controller 注解的控制器进行管理。
注解了 @ControllerAdvice 的类的方法可以使用 @ExceptionHandler、 @InitBinder、 @ModelAttribute 注解到方法上,这对所有注解了 @RequestMapping 的控制器内的方法都有效。
- @ExceptionHandler:用于捕获所有控制器里面的异常,并进行处理。
- @InitBinder:用来设置 WebDataBinder,WebDataBinder 用来自动绑定前台请求参数到 Model 中。
- @ModelAttribute:@ModelAttribute 本来的作用是绑定键值对到 Model 里,此处是让全局的@RequestMapping 都能获得在此处设置的键值对。