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

Cha*_*ntz 10 java spring web.xml spring-mvc http-status-code-404

(问题末尾发布的解决方案)

我正在构建一个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 {
...
}
Run Code Online (Sandbox Code Playgroud)

public class WebAppInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {
...
}
Run Code Online (Sandbox Code Playgroud)

我现在正在尝试为404页面添加一个global/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() {
    }

}
Run Code Online (Sandbox Code Playgroud)

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

解决方案 我做了@Sotirios 在这里提到的.这是我的部分WebAppInitializer代码,它将正确设置调度程序.

public class WebAppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    ...

    @Override
    protected void registerDispatcherServlet(ServletContext servletContext) {

        String servletName = super.getServletName();
        Assert.hasLength(servletName, "getServletName() may not return empty or null");

        WebApplicationContext servletAppContext = super.createServletApplicationContext();
        Assert.notNull(servletAppContext,
                "createServletApplicationContext() did not return an application " +
                "context for servlet [" + servletName + "]");

        DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);

        //>>> START: My custom code, rest is exqact copy of the super class
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        //>>> END

        ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
        Assert.notNull(registration,
                "Failed to register servlet with name '" + servletName + "'." +
                "Check if there is another servlet registered under the same name.");

        registration.setLoadOnStartup(1);
        registration.addMapping(getServletMappings());
        registration.setAsyncSupported(isAsyncSupported());

        Filter[] filters = getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            for (Filter filter : filters) {
                super.registerServletFilter(servletContext, filter);
            }
        }

        super.customizeRegistration(registration);
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

虽然我对这个解决方案并不是特别满意,因为我唯一的自定义代码是1行,而rest是直接从超类中复制的.我希望有一个更好的方法来做到这一点.

Sot*_*lis 15

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

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

DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
Run Code Online (Sandbox Code Playgroud)


Abo*_*ang 6

启用DispatcherServlet通过web.xml configuartion抛出NoHandlerFoundException.

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>
Run Code Online (Sandbox Code Playgroud)