簡體   English   中英

@ControllerAdvice異常處理與@ResponseStatus一起

[英]@ControllerAdvice exception handling together with @ResponseStatus

我有@ControllerAdvice類,它處理一組異常。 除了我們有其他一些例外,這些例外還帶有@ResponseStatus批注。 為了結合這兩種方法,我們使用博客文章中描述的技術: http : //spring.io/blog/2013/11/01/exception-handling-in-spring-mvc ,即在ControllerAdvice我們在下面處理通用Exception道路:

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        // If the exception is annotated with @ResponseStatus rethrow it and let
        // the framework handle it - like the OrderNotFoundException example
        // at the start of this post.
        // AnnotationUtils is a Spring Framework utility class.
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
            throw e;

        // Otherwise setup and send the user to a default error-view.
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }

它的工作原理像一個超級按鈕,但是,使用此技術會導致錯誤,並在應用程序日志中顯示以下文本:

2014-06-11 15:51:32.907 ERROR o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: ...

這是由ExceptionHandlerExceptionResolver的這段代碼引起的:

try {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking @ExceptionHandler method: " + exceptionHandlerMethod);
            }
            exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
        }
        catch (Exception invocationEx) {
            logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
            return null;
        }

是否有人知道如何將這兩種方法正確地結合在一起以進行異常處理,以避免日志中的錯誤?

謝謝,揚

這是一個老問題,但是我今天剛遇到這個問題,並且找到了比禁用ExceptionHandlerExceptionResolver日志記錄更好的解決方案。 事實證明,可以通過升級到最新版本的spring框架(對我來說是4.3.8)解決了該問題。 ExceptionHandlerExceptionResolver已修復,可以檢測是否從@ExceptionHandler拋出了原始異常。 在這種情況下,不再記錄異常。

當我錯過這個import時,我遇到了同樣的問題:

import org.springframework.http.HttpStatus;

Eclipse沒有提供我將其添加到Quick Fix中的功能 ,而是手動添加了該行,它有所幫助。

我以稍微不同的方式處理它,我認為可以解決您的問題。

因為我知道基本上我想處理404而不是500的任何色調,所以我會尋找一個NOT_FOUND狀態並進行相應的發送,這似乎可行,並且您不會重新拋出異常。

這意味着

@ControllerAdvice
public class MVCExceptionHandler {
    private static final Logger log = LogManager.getLogger();

    @ExceptionHandler(Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, HttpServletResponse res, Exception ex) throws Exception {

        // If the exception is annotated with @ResponseStatus check if it's a 404 in which case deal with it, otherwise 500 it.
        if (AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class) != null) {
            ResponseStatus rs = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
            if (HttpStatus.NOT_FOUND.equals(rs.value())) {
                res.setStatus(HttpStatus.NOT_FOUND.value());
                return new ModelAndView("error/404");
            }
        }

        log.error("Error while loading", ex);

        return new ModelAndView("error/500");

    }
}

問題是您在引發異常,而不是返回ModelAndView 本質上,您試圖在ControllerAdvice類中重新實現ResponseStatusExceptionResolver 您可以做到這一點(例如,通過ResponseStatusExceptionResolver的復制/粘貼代碼),但是除了重復之外,該方法也不完整。 對於某些內置的異常,Spring還附帶有DefaultHandlerExceptionResolver ,這種方法可能無法正確處理這些異常。

相反,我所做的是在ControllerAdvice類中沒有Exception.class處理程序。 我不知道這是否是最好的解決方案,但這是我所知道的最好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM