主流框架【第10期】--SpringMVC全局异常处理
主流框架【第10期】--SpringMVC全局异常处理
导读:
大家好,我是老田。今天我们重点梳理SpringMVC的全局异常处理实现方式。在项目中为了用户体验和安全考虑,全局统一异常处理是必须的。
1.全局异常处理思路
我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信 息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层 还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来, 既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
目前系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端 控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统 一异常处理。
2.springmvc全局异常处理的方式
使用springmvc提供简单异常处理器SimpleMappingExceptionResolver
实现spring的异常处理接口handleerExceptionResolver自定义处理异常
使用 @ExceptionHandler注解实现异常处理
使用 @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;
}
}
@ControllerAdvice 表示这是一个增强版的 Controller,主要用来做全局数据处理
@ExceptionHandler 表示这是一个异常处理方法,这个注解的参数,表示需要拦截的异常,参数为 Exception 表示拦截所有异常,这里也可以具体到某一个异常,如果具体到某一个异常,那么发生了其他异常则不会被拦截到。
异常方法的定义和 Controller 中方法的定义一样,可以返回 ModelAndview,也可以返回 String 或者 void
也可以通过添加@ResponseBody返回JSON数据
博观而约取,厚积而薄发!
--END--