SpringBoot 全局异常处理进阶:使用 @ControllerAdvice 对不同的 Controller 分别捕获异常并处理

引言

之前发表过一篇 SpringBoot 对 controller 层捕获全局异常并处理的方法(@ControllerAdvice 和 @ExceptionHandler),介绍了如何在 SpringBoot 工程中对 Controller 配置全局异常处理。后来在实际工程中,又有了如下需求:有些接口在发生异常时,需要持久化错误信息,而有的接口则不需要。如果使用了全局异常处理,那每次发生了异常,还需要判断是哪个接口发生的异常,进而选择是否持久化错误日志。那能不能对全局异常进行配置,对不同类型的接口使用不同的全局异常进行处理呢?

经过查阅文档发现,Spring 提供了对 @ControllerAdvice 注解的配置,我们可以通过配置 @ControllerAdvice 指定拦截范围。

@ControllerAdvice 指定 Controller 范围

根据 API,我们可以看到注解 @ControllerAdvice 有如下几种配置:

basePackages

//@ControllerAdvice("cn.myz.demo.controller")
//@ControllerAdvice(value = "cn.myz.demo.controller")
@ControllerAdvice(basePackages = {"cn.myz.demo.controller"})
public class GlobalExceptionHandler {}

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

basePackageClasses

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

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

assignableTypes

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

assignableTypes:指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理。

annotations

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

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

例子

这里我用 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 httpServletRequest
     * @param e                  异常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public String exceptionHandler(HttpServletRequest httpServletRequest, Exception e) {
        log.error("GlobalExceptionHandler1 服务错误");
        return "GlobalExceptionHandler1 服务错误";
    }
}
@ControllerAdvice(assignableTypes = {MyController2.class})
@Slf4j
public class GlobalExceptionHandler2 {

    /**
     * 处理 Exception 异常
     *
     * @param httpServletRequest httpServletRequest
     * @param e                  异常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public String exceptionHandler(HttpServletRequest httpServletRequest, 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

返回:

{
    "timestamp": "2019-03-15T06:40:06.224+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "No message available",
    "path": "/test3"
}

即 MyController3 异常没有被全局异常捕获。

以上就是全局异常的分类处理。


站在前人的肩膀上前行,感谢以下资料的支持。


原文作者: 一只因特马
原文链接: https://www.interhorse.cn/a/799497670/
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-ND 许可协议。转载请注明出处!

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当我们在编写 Spring MVC 应用程序时,我们可以使用 @ControllerAdvice 注解或者在 Controller使用 @ExceptionHandler 注解来处理异常。@ControllerAdvice 注解可以用于全局异常处理,而 @ExceptionHandler 注解则用于处理特定的异常。 下面是一个使用 @ControllerAdvice 注解处理异常的示例: ``` @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ModelAndView handleException(Exception e) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.setViewName("error"); return mav; } } ``` 在上面的示例中,我们定义了一个名为 GlobalExceptionHandler 的类,并使用 @ControllerAdvice 注解将其标记为全局异常处理器。我们还使用 @ExceptionHandler 注解来处理 Exception 类型的异常。当应用程序中出现 Exception 类型的异常时,Spring MVC 将会调用 handleException 方法来处理异常,并返回一个包含异常信息的 ModelAndView 对象。 如果我们想要在 Controller处理特定的异常,我们可以使用 @ExceptionHandler 注解。下面是一个使用 @ExceptionHandler 注解处理特定异常的示例: ``` @Controller public class UserController { @ExceptionHandler(UserNotFoundException.class) public ModelAndView handleUserNotFoundException(UserNotFoundException e) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.setViewName("userNotFound"); return mav; } @GetMapping("/users/{id}") public String getUser(@PathVariable Long id) { User user = userService.getUserById(id); if (user == null) { throw new UserNotFoundException("User not found with id " + id); } return "userDetails"; } } ``` 在上面的示例中,我们定义了一个名为 UserController 的类,并使用 @Controller 注解将其标记为一个 Controller。我们还使用 @ExceptionHandler 注解来处理 UserNotFoundException 类型的异常。当应用程序中出现 UserNotFoundException 类型的异常时,Spring MVC 将会调用 handleUserNotFoundException 方法来处理异常,并返回一个包含异常信息的 ModelAndView 对象。 另外,我们还定义了一个名为 getUser 的方法来获取用户信息。如果用户不存在,我们将会抛出一个 UserNotFoundException 异常,该异常将会被 handleUserNotFoundException 方法处理
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值