问题

Spring Boot-处理 NoHandlerFoundException


阅读有关如何处理 NoHandlerFoundException 的 Spring 参考指南,发现 Spring 默认将 throwExceptionIfNoHandlerFound 设置为 false

知道这一点后,我认为将此参数设置为 true 是个好主意。

我正在使用 Spring Boot。

这样做了:

MyConfig.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

@SpringBootApplication
public class MyConfig {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyConfig.class, args);
        context.getBean(DispatcherServlet.class).setThrowExceptionIfNoHandlerFound(true);

        // ...
    }
}

好的,现在 throwExceptionIfNoHandlerFound 等于 true。然而,这并没有按预期工作。DispatcherServlet 继续不抛出 NoHandlerFoundException。这样一来,我就无能为力了。

CustomExceptionHandler.java(这不起作用)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

经过一番搜索,发现添加 @EnableWebMvc 应该可以。然后,我确实将此注解添加到我的 CustomExceptionHandler

CustomExceptionHandler.java (这确实有效)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@EnableWebMvc
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

这样,手柄就起作用了。但是,我使用的是 Spring Boot。Spring Boot 文档建议如果我插入 @EnableWebMvc,我将失去一些 Spring Boot MVC 自动配置功能,因为我将完全控制 Spring MVC。(看这里)。

“如果你想完全控制 Spring MVC,你可以添加你自己的带有 @EnableWebMvc 注释的 @Configuration。”

我会失去 Spring MVC 自动配置吗?我的意思是,@EnableWebMvc,就我而言,它不在 @Configuration 类中。

我的问题是基于我不确定上面的代码是如何工作的,我想知道是否有另一种方法可以做到这一点而不会丢失 Spring MVC 自动配置。有人可以解释一下吗?

推荐答案

Spring Boot 自动配置会自动添加一个 ResourceHttpRequestHandler 来处理服务静态资源。默认情况下,此处理程序映射到 /** 并且是处理程序链中的最后一项。

这意味着 DispatcherServlet 不会抛出 NoHandlerFoundException 因为它找到了资源处理程序。资源处理程序处理请求并调用 response.sendError(HttpServletResponse.SC_NOT_FOUND) 以返回 404。

如果您不希望这种行为,您可以将以下内容添加到您的 application.properties

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

将配置调度程序 servlet 以引发异常,并告诉 Spring Boot 不要注册资源处理程序。

在您沿着这条路线走得太远之前,您可能想查看参考文档的这一部分,看看以不同的方式处理这些错误是否会更好。您的问题并不完全清楚您在错误处理程序中实际尝试做什么,但如果它只是处理 404,那么可能有更好的方法。