vlambda博客
学习文章列表

主流框架【第10期】--SpringMVC全局异常处理

主流框架【第10期】--SpringMVC全局异常处理

导读:

    大家好,我是老田。今天我们重点梳理SpringMVC的全局异常处理实现方式。在项目中为了用户体验和安全考虑,全局统一异常处理必须的。

1.全局异常处理思路

我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信 息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层 还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来, 既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。

目前系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端 控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统 一异常处理。

2.springmvc全局异常处理的方式

  1. 使用springmvc提供简单异常处理器SimpleMappingExceptionResolver

  2. 实现spring的异常处理接口handleerExceptionResolver自定义处理异常

  3. 使用 @ExceptionHandler注解实现异常处理

  4. 使用 @ControllerAdvice+ @ ExceptionHandler 注解

3.SimpleMappingExceptionResolver实现全局异常处理

springmvc中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了 HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。我们要使用这个自带的异常处理 器,首先得在springmvc.xml文件中配置该处理器:

 <!-- springmvc提供的简单异常处理器 -->
 <bean
       class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolve
              r">
     <!-- 定义默认的异常处理页面 -->
     <property name="defaultErrorView" value="/WEB-INF/pages/error.jsp"/>
     <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为
 exception -->
     <property name="exceptionAttribute" value="ex"/>
     <!-- 定义需要特殊处理的异常,这是重要点 -->
     <property name="exceptionMappings">
         <props>
             <prop key="java.lang.Exception">/WEB-INF/pages/error.jsp</prop>
         </props>
         <!-- 还可以定义其他的自定义异常 -->
     </property>
 </bean>
 

从上面的配置来看,最重要的是要配置特殊处理的异常,这些异常一般都是我们自定义的,根据实际情况 来自定义的异常,然后也会跳转到不同的错误显示页面显示不同的错误信息。

使用SimpleMappingExceptionResolver进行异常处理,具有集成简单、有良好的扩展性(可以任意增加自定义的异常和异常显示页面)、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。

4.HandlerExceptionResolver自定义处理异常

Spring MVC 通过 HandlerExceptionResolver 处理程序异常,包括处理器异常、数据绑定异常以及控制器执行时发生的异常。HandlerExceptionResolver 仅有一个接口方法,源码如下。

 public interface HandlerExceptionResolver {
     @Nullable
     ModelAndView resolveException(
         HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
 }

自定义异常处理类

 package com.tian.config;
 import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.HandlerExceptionResolver;
 import org.springframework.web.servlet.ModelAndView;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 @Component
 public class MyExceptionResolver implements HandlerExceptionResolver {
     @Override
     public ModelAndView resolveException(HttpServletRequest
                                          httpServletRequest, HttpServletResponse httpServletResponse, Object o,
                                          Exception e) {
         System.out.println("这里是全局异常处理类");
         //在形参位置Exception e 捕获的是出现的异常对象,可以通过
         // if(ex instanceof MyException) {
         // MyException = (MyException) ex;
         // }
         ModelAndView modelAndView = new ModelAndView("error");
         modelAndView.addObject("errorCode","错误信息提示");
         return modelAndView;
    }
 }
 

在自定义的异常处理器中能获取导致出现异常的对象,有利于提供更详细的异常处理信息。一般用这种自 定义的全局异常处理器比较多

5.使用 @ExceptionHandler注解实现异常处理

使用 @ExceptionHandler 注解实现异常处理,具有集成简单、有扩展性好(只需要将要异常处理的 Controller 类继承于 BaseController 即可)、不需要附加 Spring 配置等优点,但该方法对已有代码存在入侵性(需要修改已有代码,使相关类继承于 BaseController),在异常处理时不能获取除异常以外的数据。

使用 @ExceptionHandler注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个 Controller里面。

 public class BaseController {
     @ExceptionHandler
     public String exc(HttpServletRequest request,HttpServletResponse
                       response,Exception ex){
         request.setAttribute("ex", ex);
         System.out.println("-----------这里是异常处理类-----------");
         return "error";
    }
 }

6.使用 @ControllerAdvice+ @ ExceptionHandler 注解

@ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个Controller里 面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。也就是说, @controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

 @ControllerAdvice//表示这是一个增强版的 Controller,主要用来做全局数据处理
 public class MyException {
     @ExceptionHandler(Exception.class)
     public ModelAndView myExceptionDemo(Exception e) {
         ModelAndView error = new ModelAndView("error");
         error.addObject("errorCode", e.getMessage());
         return error;
    }
 }
  1. @ControllerAdvice 表示这是一个增强版的 Controller,主要用来做全局数据处理

  2. @ExceptionHandler 表示这是一个异常处理方法,这个注解的参数,表示需要拦截的异常,参数为 Exception 表示拦截所有异常,这里也可以具体到某一个异常,如果具体到某一个异常,那么发生了其他异常则不会被拦截到。

  3. 异常方法的定义和 Controller 中方法的定义一样,可以返回 ModelAndview,也可以返回 String 或者 void

  4. 也可以通过添加@ResponseBody返回JSON数据



博观而约取,厚积而薄发!



--END--