404 error redirect in Spring with java config

前端 未结 9 1113
-上瘾入骨i
-上瘾入骨i 2020-11-27 04:46

As you know, in XML, the way to configure this is:


    404
    /my-custom-page-not-fo         


        
相关标签:
9条回答
  • 2020-11-27 04:52

    For Java config there is a method setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) in DispatcherServlet. By settting it to true I guess you are doing same thing

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

    then you can can this NoHandlerFoundException.class in controller advice as stated in above answer

    it will be like something

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 04:53

    In your web configuration class,

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter 
    

    Declare a bean as follows,

    @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);
        }
      };
    }
    

    Add the mentioned html files(401.html .etc) to /src/main/resources/static/ folder.

    Hope this helps

    0 讨论(0)
  • 2020-11-27 04:55

    A solution for Spring 5 and Thymeleaf 3.

    In MyWebInitializer, enable exception throwing with setThrowExceptionIfNoHandlerFound(). We need to do casting to DispatcherServlet.

    @Configuration
    public class MyWebInitializer extends
            AbstractAnnotationConfigDispatcherServletInitializer {
    
            ...
    
            @Override
            protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
                var dispatcher = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
                dispatcher.setThrowExceptionIfNoHandlerFound(true);
                return dispatcher;
            }
        }
    

    Create a controller advice with @ControllerAdvice and add error message to the ModealAndView.

    @ControllerAdvice
    public class ControllerAdvisor {
    
        @ExceptionHandler(NoHandlerFoundException.class)
        public ModelAndView handle(Exception ex) {
    
            var mv = new ModelAndView();
            mv.addObject("message", ex.getMessage());
            mv.setViewName("error/404");
    
            return mv;
        }
    }
    

    Create 404 error template, which displays the error message. Based on my configuration, the file is src/main/resources/templates/error/404.html.

    <!doctype html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>Resource not found</title>
    </head>
    <body>
    
    <h2>404 - resource not found</h2>
    
    <p>
        <span th:text="${message}" th:remove="tag"></span>
    </p>
    
    </body>
    </html>
    

    For completeness, I add the Thymeleaf resolver configuration. We configure the Thymeleaf templates to be in templates directory on the classpath.

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"com.zetcode"})
    public class WebConfig implements WebMvcConfigurer {
    
        @Autowired
        private ApplicationContext applicationContext;
    
        ...
    
        @Bean
        public SpringResourceTemplateResolver templateResolver() {
    
            var templateResolver = new SpringResourceTemplateResolver();
    
            templateResolver.setApplicationContext(applicationContext);
            templateResolver.setPrefix("classpath:/templates/");
            templateResolver.setSuffix(".html");
    
            return templateResolver;
        }
        ...
    }
    
    0 讨论(0)
  • 2020-11-27 04:57

    The most clean solution since spring 4.2 RC3 is using the new createDispatcherServlet hook within the class extending AbstractDispatcherServletInitializer (or indirectly through extending AbstractAnnotationConfigDispatcherServletInitializer) like this:

    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;
        }
    }
    

    Then you can use a global @ControllerAdvice (a class that is annotated with @ControllerAdvice) as described in the reference docs. Within the advice you can handle the NoHandlerFoundException with an @ExceptionHandler as described here.

    This could look something like this:

    @ControllerAdvice
    public class NoHandlerFoundControllerAdvice {
    
        @ExceptionHandler(NoHandlerFoundException.class)
        public ResponseEntity<String> handleNoHandlerFoundException(NoHandlerFoundException ex) {
            // prepare responseEntity
            return responseEntity;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-27 05:05

    In springboot it is even simplier. Because of Spring autoconfiguration stuff, spring creates a bean org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties. This class is annotated with @ConfigurationProperties(prefix = "spring.mvc") and therefore it will seek for properties with spring.mvc prefix.

    Part from javadoc:

    Annotation for externalized configuration. Add this to a class definition or a
    * @Bean method in a @Configuration class if you want to bind and validate
    * some external Properties (e.g. from a .properties file).
    

    You just have to add to your i.e. application.properties file following properties:

     spring.mvc.throwExceptionIfNoHandlerFound=true
     spring.resources.add-mappings=false //this is for spring so it won't return default handler for resources that not exist
    

    and add exception resolver as follows:

    @ControllerAdvice
    public class ExceptionResponseStatusHandler {
        @ExceptionHandler(NoHandlerFoundException.class)
        public ModelAndView handle404() {
            var out = new ModelAndView();
            out.setViewName("404");//you must have view named i.e. 404.html
            return out;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 05:06

    In Spring Framework, there are number of ways of handing exceptions (and particularly 404 error). Here is a documentation link.

    • First, you can still use error-page tag in web.xml, and customize error page. Here is an example.
    • Second, you can use one @ExceptionHandler for all controllers, like this:

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

      For this to work, set throwExceptionIfNoHandlerFound property to true for DispatcherServlet in web.xml:

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

      You can also pass some objects to error view, see javadoc for this.

    0 讨论(0)
提交回复
热议问题