【问题标题】:HOWTO handle 404 exceptions globally using Spring MVC configured using Java based Annotations如何使用基于 Java 的注释配置的 Spring MVC 全局处理 404 异常
【发布时间】:2014-08-21 07:53:04
【问题描述】:

我正在构建一个 Spring 4 MVC 应用程序。它完全使用 Java Annotations 进行配置。没有web.xml。该应用程序是通过使用AbstractAnnotationConfigDispatcherServletInitializerWebMvcConfigurerAdapter 的实例来配置的,如下所示,

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.*"})
@EnableTransactionManagement
@PropertySource("/WEB-INF/properties/application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
...
}

public class WebAppInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {
...
}

我现在正在尝试为 404 页添加一个全局/catch-all 异常处理程序,即HttpStatus.NOT_FOUND,但没有成功。以下是我尝试的一些方法。

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;

@ControllerAdvice
public class GlobalExceptionHandlerController {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
            ModelAndView mav = new ModelAndView();
            return mav;
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleExceptiond (NoHandlerFoundException ex) {
            ModelAndView mav = new ModelAndView();
            return mav;
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public void handleConflict() {

    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoSuchRequestHandlingMethodException.class)
    public void handlesdConflict() {
    }

}

这些方法都不会被执行。我不知道如何处理这个问题。我不想使用web.xml,因为我必须为此创建一个。

【问题讨论】:

  • 我不知道他们为什么没有通过一些protected 方法使DispatcherServlet 可见,但自定义解决方案似乎不错。
  • 为什么不直接覆盖 createDispatcherServlet

标签: java spring spring-mvc http-status-code-404 web.xml


【解决方案1】:

By default, the DispatcherServlet does not throw a NoHandlerFoundException.你需要启用它。

AbstractAnnotationConfigDispatcherServletInitializer 应该让您覆盖 DispatcherServlet 的创建方式。这样做并打电话给

DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);

【讨论】:

  • 感谢@Sotirios 的回复。但我似乎无法在AbstractAnnotationConfigDispatcherServletInitializer 中获得dispatcherServlet
  • @Chantz 覆盖registerDispatcherServlet。查看超类型的实现以了解该做什么。
  • 一年后...有更简单的方法吗?我通常不会在我的 Initializer 中覆盖 registerDispatcherServlet,所以我觉得这个方法太冗长了。所有这些行都重写只是为了添加一行。
  • @Link 看源码,好像没改过。
  • 但是你可以通过添加一行来覆盖 createDispatcherServlet,就像我提到的那样
【解决方案2】:

启用 DispatcherServlet 通过 web.xml 配置抛出 NoHandlerFoundException。

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>

【讨论】:

    【解决方案3】:

    除了覆盖registerDispatcherServlet 之外,还可以覆盖createDispatcherServlet 方法,如下所示。

    @Override
        protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
            DispatcherServlet ds = new DispatcherServlet(servletAppContext);
            ds.setThrowExceptionIfNoHandlerFound(true);
            return ds;
        }
    

    【讨论】:

      【解决方案4】:

      我无法评论@Ysak(声誉

      我将从另一个指南中添加,我还在我的 WebConfig 中配置了 DefaultServletHandling 以解决一个单独的问题,如下所示:

      @Configuration
      @EnableWebMvc
      @ComponentScan("com.acme.tat.controllers")
      public class WebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
      ...
      @Override
      public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
              configurer.enable();
      }
      
      }
      

      启用此设置后,不会引发异常。一旦我删除了这一行并设置了手动 resourceHandlers 一切都按预期工作。

      由于这种简单的单行方法,我花了大约 2.5 小时来设置 404 重定向。

      【讨论】:

        【解决方案5】:

        我通过 application.yml 中的以下条目解决了问题

         server.error.whitelabel.enabled: false
         spring.mvc.throw-exception-if-no-handler-found: true
        

        以及下面的ControllerExceptionHandler:

        @ControllerAdvice
        public class ControllerExceptionHandler {
        
        @ExceptionHandler(Exception.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String processMethodNotSupportedException(Exception exception) {
            exception.printStackTrace();
            return "error";
        }
        
        }
        

        最后但同样重要的是,我添加了一个模板“/html/error.html”

        【讨论】:

        • SpringBoot 2.0版本之后,使用spring.mvc.throwExceptionIfNoHandlerFound: true
        猜你喜欢
        • 2021-08-19
        • 2016-11-18
        • 2015-07-11
        • 2014-09-11
        • 1970-01-01
        • 2015-05-14
        • 2018-02-13
        • 1970-01-01
        相关资源
        最近更新 更多