Configure spring boot to redirect 404 to a single page app [duplicate]

This is the full Spring Boot 2.0 example:

@Configuration
public class WebApplicationConfig implements WebMvcConfigurer {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/notFound").setViewName("forward:/index.html");
}


@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
    return container -> {
        container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                "/notFound"));
    };
  }

}

This should do the trick: Add an error page for 404 that routes to /notFound, and forward that to your SPA (assuming the entry is on /index.html):

@Configuration
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/notFound").setViewName("forward:/index.html");
    }


    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                    "/notFound"));
        };
    }

}

In case anyone stumbles here looking for how to handle Angular/React/other routes and paths in a Spring Boot app - but not always return index.html for any 404 - it can be done in a standard Spring controller RequestMapping. This can be done without adding view controllers and/or customizing the container error page.

The RequestMapping supports wild cards, so you can make it match against a set of well known paths (ie. angular routes etc.) in your application and only then return forward index.html:

@Controller 
public class Html5PathsController { 

    @RequestMapping( method = {RequestMethod.OPTIONS, RequestMethod.GET}, path = {"/path1/**", "/path2/**", "/"} )
    public String forwardAngularPaths() { 
        return "forward:/index.html"; 
    } 
}

Another option (borrowed from an old Spring article here: https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii) is to use a naming convention:

@Controller 
public class Html5PathsController { 

    @RequestMapping(value = "/{[path:[^\\.]*}")
    public String redirect() {
        return "forward:/index.html";
    } 
}

The above configuration will match all paths that do not contain a period and are not already mapped to another controller.


//add this controller : perfect solution(from jhipster)
@Controller
public class ClientForwardController {
    @GetMapping(value = "/**/{path:[^\\.]*}")
    public String forward() {
        return "forward:/";
    }
}