【问题标题】:Spring MVC @ExceptionHandler method in controller never being invoked控制器中的 Spring MVC @ExceptionHandler 方法永远不会被调用
【发布时间】:2012-04-12 04:20:18
【问题描述】:

我有一个带有一些简单 REST 服务请求的 Spring MVC 控制器。当从我的服务中抛出特定异常时,我想添加一些错误处理,但是我无法让使用 @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!");
}

【问题讨论】:

    标签: java rest spring-mvc


    【解决方案1】:

    当您以这种方式定义方法时,我发现@ExceptionHandler 可以与Throwable 一起使用:

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

    在这种情况下,方法只有一个Throwable 类型的参数。如果我尝试在此方法中使用一些附加参数(我尝试使用 Model),我会收到 500 异常(此方法未调用)。但是,当附加参数是 HttpServlerRequest 或 HttpServlerResponse 时,这仍然有效。

    【讨论】:

      【解决方案2】:

      令人沮丧的是,我也遭受了这种痛苦。我发现如果你错误地实现了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);
                  }
              }
      

      【讨论】:

        【解决方案3】:

        这个tip on the Spring forum 可以帮助你。

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

        如果 XML 文件已经包含另一个 ExceptionResolver(如 SimpleMappingExceptionResovler,Spring 不会自动为您添加任何其他解析器。所以像这样手动添加注释解析器:

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

        应该启用@HandlerException 处理。

        【讨论】:

        • AnnotationMethodHandlerExceptionResolver 现在已被弃用,因此这对新版本的 Spring 没有帮助。
        • 使用这个 bean 并将 p:order 属性设置为最高优先级 (1) 可以解决我的问题。
        • @MattFriedman 只是用 org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver 替换 AnnotationMethodHandlerExceptionResolver 为我工作
        【解决方案4】:

        它不起作用,因为当您返回 String 时,您会返回视图名称。

        现在你的 Spring MVC 控制器正在搜索这个方法永远不会被调用!为什么不?!查看并可以找到。

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

        【讨论】:

        • 这很可能会导致 404,而不是 500。
        • 对不起,关键是该方法永远不会被调用,所以返回的内容无关紧要。我更改了返回的内容。
        猜你喜欢
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多