HOWTO 使用基于 Java 的注解配置的 Spring MVC 全局处理 404 异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24498662/
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-08-14 12:35:57  来源:igfitidea点击:

HOWTO handle 404 exceptions globally using Spring MVC configured using Java based Annotations

javaspringspring-mvchttp-status-code-404web.xml

提问by Chantz

I am building a Spring 4 MVC app. And it is completely configured using Java Annotations. There is no web.xml. The app is configured by using instance of AbstractAnnotationConfigDispatcherServletInitializerand WebMvcConfigurerAdapterlike so,

我正在构建一个 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 {
...
}

and

public class WebAppInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {
...
}

I am now trying to add a global/catch-all exception handler for 404 pages i.e. HttpStatus.NOT_FOUNDbut no success. Below are some of the ways I tried.

我现在正在尝试为 404 页添加全局/捕获所有异常处理程序,即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() {
    }

}

None of these methods get executed. I am at a loss as to how to handle this. I do not want to use web.xmlbecasue then I would have to create one just for this.

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

采纳答案by Sotirios Delimanolis

By default, the DispatcherServletdoes not throw a NoHandlerFoundException.You need to enable that.

默认情况下,DispatcherServlet不会抛出NoHandlerFoundException. 你需要启用它。

The AbstractAnnotationConfigDispatcherServletInitializershould let you override how the DispatcherServletis created. Do that and call

AbstractAnnotationConfigDispatcherServletInitializer应该让你重写如何DispatcherServlet被创建。这样做并打电话

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

回答by Aborn Jiang

Enable DispatcherServlet throw a NoHandlerFoundException through web.xml configuartion.

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

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

回答by Ysak

Instead overriding registerDispatcherServletone can override the createDispatcherServletmethod as follows.

相反,覆盖registerDispatcherServlet一个可以覆盖该createDispatcherServlet方法,如下所示。

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

回答by user3559338

I can't comment on the above post by @Ysak (reputation<50), however I can confirm that this method does work with the setup described by the OP.

我无法对@Ysak(声誉<50)的上述帖子发表评论,但是我可以确认此方法确实适用于 OP 描述的设置。

I will add that from another guide I also had the DefaultServletHandling configured in my WebConfig to fix a separate issue, as below:

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

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

}

With this set to enable, there is no Exception thrown. Once I removed this line and set up manual resourceHandlers everything worked as expected.

启用此设置后,不会抛出异常。一旦我删除了这一行并设置了手动资源处理程序,一切都按预期工作。

It took me around 2.5 hours to set up 404 redirecting because of this simple one line method.

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

回答by Simon Ludwig

I resolved the problem with the following entry in my application.yml

我在 application.yml 中使用以下条目解决了问题

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

and the following ControllerExceptionHandler:

以及以下 ControllerExceptionHandler:

@ControllerAdvice
public class ControllerExceptionHandler {

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

}

and last but not least i added a template "/html/error.html"

最后但并非最不重要的是我添加了一个模板“/html/error.html”