Spring MVC控制器中的@ExceptionHandler方法从未被调用

14

我有一个Spring MVC控制器,其中包含一些简单的REST服务请求。当我的服务抛出特定的异常时,我想添加一些错误处理,但我无法使带有@ExceptionHandler注释的处理程序方法被调用。以下是一个我故意抛出异常来尝试让处理程序方法接管的服务。处理程序方法从未被调用,Spring只会向调用客户端返回500错误。你有任何关于我做错了什么的想法吗?

@ExceptionHandler(IOException.class)
public ModelAndView handleIOException(IOException ex, HttpServletRequest request, HttpServletResponse response) {
    response.sendError(HttpServletResponse.SC_FORBIDDEN);
    System.out.println("It worked!");
    return new ModelAndView();
}

@RequestMapping(value = "/json/remove-service/{id}", method = RequestMethod.DELETE)
public void remove(@PathVariable("id") Long id) throws IOException {
    throw new IOException("The handler should take over from here!");
}
4个回答

14
令人沮丧的是,我也经历过这种情况。我发现如果你错误地使用了 Throwable 而不是 Exception , 异常解析器将会把你的 Throwable 重新抛出为一个 IllegalStateException ,这将无法触发你的 @ExceptionHandler
如果你实现了 Throwable 而不是 Exception ,请尝试改为使用 Exception
以下是相关的代码,来自于 InvocableHandlerMethod
catch (InvocationTargetException e) {
            // Unwrap for HandlerExceptionResolvers ...
            Throwable targetException = e.getTargetException();
            if (targetException instanceof RuntimeException) {
                throw (RuntimeException) targetException;
            }
            else if (targetException instanceof Error) {
                throw (Error) targetException;
            }
            else if (targetException instanceof Exception) {
                throw (Exception) targetException;
            }
            else {
                String msg = getInvocationErrorMessage("Failed to invoke controller method", args);
                throw new IllegalStateException(msg, targetException);
            }
        }

这是一个常见的错误,今天我犯了这个错误。在我的情况下,Intellij默认通过扩展Throwable来引起了这个问题。 - Vipin

13

这个Spring论坛上的技巧可能会对你有所帮助。

很可能你已经在webmvc-servlet.xml文件中配置了DispatchServlet的bean(*-servlet.xml文件的名称可能不同)。

如果XML文件已经包含另一个ExceptionResolver(例如SimpleMappingExceptionResovler),Spring就不会自动为你添加其他解析器。因此,你需要手动添加注释解析器,如下所示:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver" />

应启用@HandlerException处理。


3
AnnotationMethodHandlerExceptionResolver 已经被弃用,在新版本的Spring中已经不再适用。 - Matt Friedman
使用将p:order属性设置为最高优先级(1)的此Bean成功解决了我的问题。 - Alex
@MattFriedman 只需要将AnnotationMethodHandlerExceptionResolver替换为org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver就可以解决我的问题。 - Stefan Haberl

4

我发现当你以这种方式定义方法时,@ExceptionHandler可以处理Throwable

@ExceptionHandler(Throwable.class)
@ResponseBody
public String handleException(Throwable e) {

}

在此情况下,该方法只有一个类型为Throwable的参数。如果我尝试在此方法中使用其他附加参数(我试过使用Model),那么我将收到500异常(此方法未被调用)。但是当使用附加参数HttpServlerRequest或HttpServlerResponse时,仍然可以正常工作。

0

这不会起作用,因为当你返回字符串时,你返回的是视图名称。

现在你的Spring MVC控制器正在寻找This method is never called! Why not?!视图,但找不到。

确保@ExceptionHandler映射到现有视图。


这很可能会导致404错误,而不是500错误。 - skaffman
1
抱歉,问题在于该方法从未被调用,因此返回值是无关紧要的。我已更改了返回值。 - 11101101b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接