Redirección de error 404 en Spring con configuración java

Como saben, en XML, la forma de configurar esto es:

 404 /my-custom-page-not-found.html  

Pero no he encontrado una manera de hacerlo en la configuración de Java. La primera forma en que lo intenté fue:

 @RequestMapping(value = "/**") public String Error(){ return "error"; } 

Y pareció funcionar, pero tiene conflictos al recuperar los recursos.

¿Hay una manera de hacerlo?

En Spring Framework, hay varias maneras de administrar excepciones (y particularmente el error 404). Aquí hay un enlace de documentación .

  • Primero, aún puede usar la etiqueta de la error-page en web.xml y personalizar la página de error. Aquí hay un ejemplo .
  • En segundo lugar, puede usar un @ExceptionHandler para todos los controladores, como este:

     @ControllerAdvice public class ControllerAdvisor { @ExceptionHandler(NoHandlerFoundException.class) public String handle(Exception ex) { return "404";//this is view name } } 

    Para que esto funcione, establezca la propiedad throwExceptionIfNoHandlerFound en true para DispatcherServlet en web.xml:

      throwExceptionIfNoHandlerFound true  

    También puede pasar algunos objetos a la vista de error, vea javadoc para esto.

La solución más limpia desde la spring 4.2 RC3 está utilizando el nuevo gancho createDispatcherServlet dentro de la clase que extiende AbstractDispatcherServletInitializer (o indirectamente extendiendo AbstractAnnotationConfigDispatcherServletInitializer ) de esta manera:

 public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class< ?>[] getRootConfigClasses() { return null; } /* ... */ @Override protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) { final DispatcherServlet dispatcherServlet = super.createDispatcherServlet(servletAppContext); dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); return dispatcherServlet; } } 

Entonces puede usar un @ControllerAdvice global (una clase que está anotada con @ControllerAdvice ) como se describe en los documentos de referencia . Dentro del consejo, puede manejar NoHandlerFoundException con @ExceptionHandler como se describe aquí .

Esto podría verse más o menos así:

 @ControllerAdvice public class NoHandlerFoundControllerAdvice { @ExceptionHandler(NoHandlerFoundException.class) public ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException ex) { // prepare responseEntity return responseEntity; } } 

Utilice la inicialización del contenedor de servlets basado en código como se describe en el documento y anule el método registerDispatcherServlet para establecer la propiedad throwExceptionIfNoHandlerFound en true:

 public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class< ?>[] getRootConfigClasses() { return null; } @Override protected Class< ?>[] getServletConfigClasses() { return new Class[] { WebConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected void registerDispatcherServlet(ServletContext servletContext) { String servletName = getServletName(); Assert.hasLength(servletName, "getServletName() may not return empty or null"); WebApplicationContext servletAppContext = createServletApplicationContext(); Assert.notNull(servletAppContext, "createServletApplicationContext() did not return an application " + "context for servlet [" + servletName + "]"); DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext); // throw NoHandlerFoundException to Controller dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); 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) { registerServletFilter(servletContext, filter); } } customizeRegistration(registration); } } 

Luego crea un manejador de excepciones:

 @ControllerAdvice public class ExceptionHandlerController { @ExceptionHandler(Exception.class) public String handleException(Exception e) { return "404";// view name for 404 error } } 

No olvide usar la anotación @EnableWebMvc en su archivo de configuración de Spring :

 @Configuration @EnableWebMvc @ComponentScan(basePackages= {"org.project.etc"}) public class WebConfig extends WebMvcConfigurerAdapter { ... } 

Respuesta simple para 100% xml gratis:

  1. Establecer propiedades para DispatcherServlet

     public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class< ?>[] getRootConfigClasses() { return new Class[] { RootConfig.class }; } @Override protected Class< ?>[] getServletConfigClasses() { return new Class[] {AppConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected void customizeRegistration(ServletRegistration.Dynamic registration) { boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true if(!done) throw new RuntimeException(); } } 
  2. Crear @ControllerAdvice :

     @ControllerAdvice public class AdviceController { @ExceptionHandler(NoHandlerFoundException.class) public String handle(Exception ex) { return "redirect:/404"; } @RequestMapping(value = {"/404"}, method = RequestMethod.GET) public String NotFoudPage() { return "404"; } } 

En tu clase de configuración web,

 @Configuration public class WebConfig extends WebMvcConfigurerAdapter 

Declara un frijol de la siguiente manera,

 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html"); ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html"); container.addErrorPages(error401Page,error404Page,error500Page); } }; } 

Agregue los archivos html mencionados ( 401.html .etc) a /src/main/resources/static/ folder.

Espero que esto ayude

Para la configuración de Java, hay un método setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) en DispatcherServlet . Al establecerlo en true , supongo que estás haciendo lo mismo

  throwExceptionIfNoHandlerFound true  

entonces puede esta NoHandlerFoundException.class en el consejo del controlador como se indica en la respuesta anterior

será como algo

 public class WebXml implements WebApplicationInitializer{ public void onStartup(ServletContext servletContext) throws ServletException { WebApplicationContext context = getContext(); servletContext.addListener(new ContextLoaderListener(context)); DispatcherServlet dp = new DispatcherServlet(context); dp.setThrowExceptionIfNoHandlerFound(true); ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", dp); dispatcher.setLoadOnStartup(1); dispatcher.addMapping(MAPPING_URL); } } 

La solución propuesta en los comentarios anteriores realmente funciona:

 @Override protected void customizeRegistration(ServletRegistration.Dynamic registration) { registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); }