我们是一个基于Spring MVC的REST应用程序。我试图使用ExceptionHandler注释来处理所有错误和异常。
我有
@ExceptionHandler(Throwable.class)
public @ResponseBody String handleErrors() {
return "error";
}
只要抛出异常并且它不适用于任何错误,它就可以工作。
我使用的是Spring 4.0。有没有解决办法?
答案 0 :(得分:6)
与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
。
答案 1 :(得分:-1)
你可以做一种Hacking来捕获Spring MVC中的Error。 首先,像这样定义一个拦截器:
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);
} }
其次,在控制器中定义一个方法,例如&#34; handleError&#34;方法:
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;
}