ExceptionHandler 不适用于 Throwable

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

我们的应用程序是基于 Spring MVC 的 REST 应用程序。我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常。

我有

    @ExceptionHandler(Throwable.class)
    public @ResponseBody String handleErrors() {
        return "error";
    }

只要抛出异常,它就会起作用,但对于任何错误都不起作用。

我正在使用Spring 4.0。有什么解决办法吗?

java rest tomcat spring-mvc web-applications
3个回答
8
投票

ExceptionHandler#value()
属性所示相反

Class<? extends Throwable>[] value() default {};

@ExceptionHandler
仅用于处理
Exception
及其子类型。

Spring 使用

ExceptionHandlerExceptionResolver
来解析带注释的处理程序,使用以下方法

doResolveHandlerMethodException(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) 

如您所见,仅接受

Exception

在此配置中,您无法使用

Throwable
处理
Error
@ExceptionHandler
类型。

我会告诉你提供自己的

HandlerExceptionResolver
实现来处理
Throwable
实例,但是你需要自己提供自己的
DispatcherServlet
(以及大部分 MVC 堆栈),因为
DispatcherServlet
catch 
Throwable
在任何可以产生重大影响的地方都有实例。


更新:

从 4.3 开始,Spring MVC 将抛出的

Throwable
值包装在
NestedServletException
实例中,并将其公开给
ExceptionHandlerExceptionResolver


0
投票

我最近尝试过这个,经过审查,我的队友向我展示了这篇文章,但在 Spring Boot 3.2.2 中,你可以很好地捕获错误!


-1
投票

您可以进行一种 Hacking 来捕获 Spring MVC 中的错误。 首先,像这样定义一个拦截器:

public class ErrorHandlingInterceptor extends HandlerInterceptorAdapter {
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
    super.afterCompletion(request, response, handler, ex);

    controller.handleError(ex.getCause(), request, response);
} }

其次,在控制器中定义一个方法,例如“handleError”方法:

    ErrorResponse errorResponse = new ErrorResponse();
    errorResponse.setExceptionId(exceptionId);
    errorResponse.setErrorMsg(ex.toString());
    errorResponse.setServerStackTrace(serverStackTrace(ex));

    response.setStatus(responseCode);
    response.setContentType("application/json");

    ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
    writer.writeValue(response.getOutputStream(), errorResponse);

最后,在 Spring 配置中配置你的拦截器。

<mvc:interceptors>
    <bean class="ErrorHandlingInterceptor" />
</mvc:interceptors>

DispatchServlet 中的代码:

            catch (Exception ex) {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// This is where to handle Exception by Spring.
// If Error happens, it will go to catch Error statement 
// which will call afterCompletion method
            mv = processHandlerException(processedRequest, response, handler, ex);
            errorView = (mv != null);
        }

        // Did the handler return a view to render?
        if (mv != null && !mv.wasCleared()) {
            render(mv, processedRequest, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                        "': assuming HandlerAdapter completed request handling");
            }
        }

        // Trigger after-completion for successful outcome.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
    }

    catch (Exception ex) {
        // Trigger after-completion for thrown exception.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    }
    catch (Error err) {
        ServletException ex = new NestedServletException("Handler processing failed", err);
        // Trigger after-completion for thrown exception.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    }
© www.soinside.com 2019 - 2024. All rights reserved.