@ControllerAdvice

1 @ControllerAdvice

@ExceptionHandler(Exception.class)注解,表示当控制器抛出Exception异常时,将会委托该方法来处理。

@controllerAdvice最为实用的一个场景就是将所有@ExceptionHandler方法收集到一个类中,这样所有的异常都能在一个地方进行一致处理。

@ControllerAdvice默认所有控制的抛出的异常都会在这个类进行处理

  • @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。

  • 在Spring中, @ControllerAdvice通过annotations(), basePackageClasses(), basePackages() 方法定制用于选择控制器子集。

  • 即把@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。非常简单,不过只有当使用@ExceptionHandler最有用,另外两个用处不大。

1.1 basePackages

@ControllerAdvice同时配置过滤多个包

//@ControllerAdvice("com.test.controller")   //配置过滤一个的时候
//@ControllerAdvice(value = "cn.test.controller")
@ControllerAdvice(basePackages={"com.test.controller", "com.test1.controller"})    //同时配置过滤多个包
public class GlobalExceptionHandler {
   ···········
}

basePackages:指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理。其中上面两种等价于 basePackages。

1.2 basePackageClasses

@ControllerAdvice(basePackageClasses = {MyController1.class})
public class GlobalExceptionHandler {}

basePackageClasses:是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理。

1.3 assignableTypes

@ControllerAdvice(assignableTypes = {MyController1.class})
public class GlobalExceptionHandler {}

assignableTypes:指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理。即被{}起来的 {MyController1.class}这个类被全局异常监控。

1.4 annotations

@ControllerAdvice(annotations = {RestController.class})
public class GlobalExceptionHandler {}

annotations:指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理。

2 示例

这里用 assignableTypes 配置指定的 Controller 进行测试。

创建三个 Controller

@Controller
public class MyController1 {

    @RequestMapping(value = "/test1")
    public void test1() {
        throw new BusinessException("1", "test1 错误");
    }
}

@Controller
public class MyController2 {
    @RequestMapping(value = "/test2")
    public void test1() {
        throw new BusinessException("2", "test2 错误");
    }
}

@Controller
public class MyController3 {
    @RequestMapping(value = "/test3")
    public void test1() {
        throw new BusinessException("3", "test3 错误");
    }
}

其中,BusinessException 是我自定义的异常类。

创建两个全局异常处理类

@ControllerAdvice(assignableTypes = {MyController1.class})
@Slf4j
public class GlobalExceptionHandler1 {

    /**
     * 处理 Exception 异常
     * @param httpServletRequest request
     * @param e                  异常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public String exceptionHandler(HttpServletRequest request, Exception e) {
        log.error("GlobalExceptionHandler1 服务错误");
        return "GlobalExceptionHandler1 服务错误";
    }
}
@ControllerAdvice(assignableTypes = {MyController2.class})
@Slf4j
public class GlobalExceptionHandler2 {

    /**
     * 处理 Exception 异常
     * @param httpServletRequest request
     * @param e                  异常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public String exceptionHandler(HttpServletRequest request, Exception e) {
        log.error("GlobalExceptionHandler2 服务错误");
        return "GlobalExceptionHandler2 服务错误";
    }
}

分别调用接口,查看错误日志

  1. 调用 localhost:8080/test1
    返回:GlobalExceptionHandler1 服务错误
    即 MyController1 异常被 GlobalExceptionHandler1 全局异常类捕获。

  2. 调用 localhost:8080/test2
    返回:GlobalExceptionHandler2 服务错误
    即 MyController2 异常被 GlobalExceptionHandler2 全局异常类捕获。

  3. 调用 localhost:8080/test3
    其中调用3返回下面的提示:
    即 MyController3 异常没有被全局异常捕获。

{
    "timestamp": "2021-06-18T16:01:06.224+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "No message available",
    "path": "/test3"
}

参考:https://blog.csdn.net/abckingaa/article/details/89601060
https://www.interhorse.cn/a/799497670/
Spring 框架 5.1.5.RELEASE API
https://www.cnblogs.com/duanxz/p/3753687.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值