java Spring MVC - 无法调用自定义 ExceptionHandler

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35988643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:51:24  来源:igfitidea点击:

Spring MVC - Failed to invoke custom ExceptionHandler

javaspring-mvcspring-boot

提问by MD Sayem Ahmed

I am receiving a strange exception in my application's server log. The exception occurs when a GET request is being made to a certain URL. The URL has the following format -

我在应用程序的服务器日志中收到一个奇怪的异常。当对某个 URL 发出 GET 请求时会发生异常。URL 具有以下格式 -

/some_list/{id}/some_method

handler for which is defined like this -

其定义如下的处理程序 -

@RestController
@Validated
public class SomeController {
    @Autowired
    private SomeService someService;

    @RequestMapping(value = "/some_list/{id}/some_method", method = RequestMethod.GET)
    public Collection<SomeObject> getCollection(
        @PathVariable @SomeCustomJavaxConstraintValidator String id,
        @RequestParam(required = true) 
            @SomeCustomJavaxConstraintValidator String someOtherID) {

        return someService.getSomething(id, someOtherID);
    }

    // other methods
}

The exception looks like this (message formatted to fit the question area) -

异常看起来像这样(消息格式化以适合问题区域)-

2016-03-13 14:46:09.956 ERROR org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - 
Failed to invoke @ExceptionHandler method: 
    public org.springframework.http.ResponseEntity<SomeEntity> 
        com.hogehoge.GenericExceptionHandler.handleServiceException(
            javax.servlet.http.HttpServletResponse, 
            com.hogehoge.CustomException)
java.lang.NullPointerException: Name is null
    at java.lang.Enum.valueOf(Enum.java:236) ~[na:1.8.0_66]
    at org.springframework.http.HttpMethod.valueOf(HttpMethod.java:27) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.http.server.ServletServerHttpRequest.getMethod(ServletServerHttpRequest.java:87) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:175) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:363) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:137) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1183) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1020) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [tomcat8-servlet-api-8.0.26.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat8-servlet-api-8.0.26.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1074) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.run(Nio2Endpoint.java:1033) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint.processSocket0(Nio2Endpoint.java:594) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint.processSocket(Nio2Endpoint.java:578) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.SecureNio2Channel.completed(SecureNio2Channel.java:86) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.SecureNio2Channel.completed(SecureNio2Channel.java:79) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) [na:1.8.0_66]
    at sun.nio.ch.Invoker.run(Invoker.java:218) [na:1.8.0_66]
    at sun.nio.ch.AsynchronousChannelGroupImpl.run(AsynchronousChannelGroupImpl.java:112) [na:1.8.0_66]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_66]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_66]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat8-util-8.0.26.jar:8.0.26]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_66]

GenericExceptionHandleris a @ControllerAdvicewhich is registered like this -

GenericExceptionHandler@ControllerAdvice这样注册的 -

@ControllerAdvice
public class GenericExceptionHandler {
    // fields and others......

    @ResponseBody
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<SomeEntity> handleServiceException(
        HttpServletResponse response, CustomException e) {

        // method implementation
    }

I could not reproduce this exception in my local environment as the exception apparently occurs at random. I tried to debug it following the stack trace, and it looks like for some reason the getMethodmethod of HttpServletRequestreturns null(!!??), and as a result HttpMethod.valueOfis throwing this exception, but I don't know why this is the case.

我无法在本地环境中重现此异常,因为该异常显然是随机发生的。我试图在堆栈跟踪之后调试它,它看起来像出于某种原因返回的getMethod方法(!!??),结果抛出了这个异常,但我不知道为什么会这样。HttpServletRequestnullHttpMethod.valueOf

Update

更新

Although this is a Spring Boot app, it is being deployed on an independent tomcat server. The POM file has been configured with the maven plugin so that the repackaging is done properly. Also the packaging of the app has been marked as war. Sample -

尽管这是一个 Spring Boot 应用程序,但它正在部署在独立的 tomcat 服务器上。POM文件已经通过maven插件进行配置,以便正确完成重新打包。此外,应用程序的包装已标记为war。样本 -

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.hogehoge</groupId>
        <artifactId>some-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>some-app</artifactId>
    <packaging>war</packaging>

    <!-- Lots of other things -->

    <build>
        <finalName>the-mighty-app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!-- Some other plugins -->
        </plugins>
    </build>
</project>

采纳答案by Dennis R

I checked latest Spring source code HttpEntityMethodProcessor.java(around line 175) and I see that code has changed slightly, now it is not possible to get NPE there. I see they switched back and forth a few times between: inputMessage.getMethod() == HttpMethod.GET and inputMessage.getMethod().equals(HttpMethod.GET)

我检查了最新的 Spring 源代码HttpEntityMethodProcessor.java(大约第 175 行),我发现代码略有变化,现在不可能在那里获得 NPE。我看到它们在以下之间来回切换: inputMessage.getMethod() == HttpMethod.GET 和 inputMessage.getMethod().equals(HttpMethod.GET)

回答by shahshi15

In regards to your original question of Failed to invoke custom ExceptionHandler, That's probably because you have your ExceptionHandleronly handling @ExceptionHandler(CustomException.class)while the exception that's actually thrown is NullPointerException. I normally also add a method (handler) for @ExceptionHandler(RuntimeException.class)in my ExceptionHandler so that I can handle runtime exceptions just like my custom exceptions.

关于您的原始问题Failed to invoke custom ExceptionHandler,这可能是因为您只有自己的ExceptionHandler处理方式,@ExceptionHandler(CustomException.class)而实际抛出的异常是NullPointerException. 我通常还会@ExceptionHandler(RuntimeException.class)在我的 ExceptionHandler 中添加一个方法(处理程序),以便我可以像处理自定义异常一样处理运行时异常。

In regards to where that nullpointer is coming from, as suggested above you could try and upgrade your Spring boot version, see if that fixes the issue.

关于空指针的来源,如上所述,您可以尝试升级 Spring boot 版本,看看是否能解决问题。