@ControllerAdvice拦截处理全局异常

马里奥 2020年09月21日 13次浏览

前言

在阅读一个开源项目时,发现作者采用@ControllerAdvice将异常的处理全给它拉到一个类里,甚妙!
在开始使用前了解下它的来历。
原文是这样描述的:

It is typically used to define @ExceptionHandler, @InitBinder, and @ModelAttribute methods that apply to all @RequestMapping methods.

大概意思是,在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute方法,并应用到所有@RequestMapping方法中。

@ControllerAdvice是类上的注解,其用法主要有三点:

  • 结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的;
  • 结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的;
  • 结合方法型注解@ModelAttribute,表示其标注的方法将会在目标Controller方法执行之前执行。

本文介绍@ExceptionHandler。

@ExceptionHandler

@ExceptionHandler的作用主要在于声明一个或多个类型的异常,当符合条件的Controller抛出这些异常之后将会对这些异常进行捕获,然后按照其标注的方法的逻辑进行处理,从而改变返回的视图信息。如下是@ExceptionHandler的属性结构:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
	Class<? extends Throwable>[] value() default {};
}

如下是使用@ExceptionHandler捕获Exception异常的例子:

@ControllerAdvice
public class TestExceptionHandler {
  @ExceptionHandler(value = Exception.class)
  public ModelAndView exceptionHandler(RuntimeException e) {
    e.printStackTrace();
    return new ModelAndView("error");
  }
}

控制器内(准确的说是@RequestMapping修饰的方法内)一旦发生异常,异常捕捉器将捕捉到,返回error页面。
前后端分离开发需要返回数据,在捕获器上加@ResponseBody即可,如下:

@ControllerAdvice
public class TestExceptionHandler {
  @ExceptionHandler(value = Exception.class)
  public Result<?> exceptionHandler(RuntimeException e) {
    e.printStackTrace();
    return Result.error(CodeMsg.SERVER_ERROR);
  }
}

Result和CodeMsg分别是返回风格和错误码,用户自定义的,这里不赘述了。

参考

ControllerAdvice (Spring Framework 5.0.0.M1 API)
Spring MVC之@ControllerAdvice详解