为什么在Spring Boot Controller中异常被@ExceptionHandler捕获,而不是被@ControllerAdvice中的@ExceptionHandler捕获?

问题描述 投票:0回答:1

在 Spring Boot MVC 应用程序中,我有一个调用服务方法的控制器:

@Controller
@RequestMapping("/registration")
public class RegistrationController {

    @GetMapping({"/email-confirmation"})
    public String emailConfirmation(@RequestParam String token) {

        internalRegistrationService.confirmEmail(token);

        return "redirect:/";
    }

    @ExceptionHandler(TokenExpiredException.class)
    public ModelAndView handleTokenExpiredException(Exception e) {

        ModelAndView mv = new ModelAndView();
        //...
        return mv;
    }
}

这个服务方法可以抛出不同的子类型

TokenException
:

@Service
public class InternalRegistrationService {

    public void confirmEmail(String token) throws TokenException {

        emailTokenValidator.validate(token);
    }
}

抛出的异常是

TokenException
TokenExpiredException
类型,它扩展了 TokenException。

除了控制器本身内部的

@ExceptionHandler
(按预期捕获
TokenExpiredException
)之外,我还有一个
@ControllerAdvice
带注释的GlobalExceptionHandler:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(TokenException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "out of cookies")
    public void handleTokenException(Exception e) {
        logger.debug("{}", e.getMessage(), e);
    }
}

此处理程序方法旨在捕获除

TokenException
之外的所有其他类型的
TokenExpiredException

不幸的是,这并不能按预期工作。 异常是在由控制器调用的服务方法内引发的。根据 Antoniossss 的这篇 post ,通过控制器冒泡的所有异常都应该委托给

@ControllerAdvice
注释了GlobalExceptionHandler。然而,事实并非如此。相反,错误会导致未捕获的 500。有人知道为什么吗?

非常感谢您的帮助

编辑

有时我会问自己,我是只是有点傻,还是彻底傻了。经过一个小时的反复试验、调试以及使用和不使用 cookie 的咖啡后,我偶然发现了一个事实,即我忘记将 ControllerAdvice 包含到类路径扫描中。我深深的羞耻...


但是,我会将这段代码保留在这里,直到工作人员中有人认为更好地摆脱它。

spring-boot spring-mvc exceptionhandler controller-advice
1个回答
0
投票

如果您希望在

@ControllerAdvice
中捕获异常,请删除控制器中的
@ExceptionHandler
,或使其更加专业化。我的意思是没有捕获控制器中的 Exception 类。

© www.soinside.com 2019 - 2024. All rights reserved.