Search code examples
javaspringspring-boot

Java Spring Boot: How to map my app root (“/”) to index.html?


How can I map my app root http://localhost:8080/ to a static index.html? If I navigate to http://localhost:8080/index.html its works fine.

My app structure is :

dirs

My config\WebConfig.java looks like this:

@Configuration
@EnableWebMvc
@ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter {
    
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("/");
  }
}

I tried to add registry.addResourceHandler("/").addResourceLocations("/index.html"); but it fails.


Solution

  • It would have worked out of the box if you hadn't used @EnableWebMvc annotation. When you do that you switch off all the things that Spring Boot does for you in WebMvcAutoConfiguration. You could remove that annotation, or you could add back the view controller that you switched off (in your WebMvcConfigurer):

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

    With more recent Spring Boot versions (3.2.3 or above) you can still do the above, but there is an alternative which is recommended by the Spring MVC developers, which is to use a @Bean of type RouterFunction. For example:

    static import org.springframework.web.servlet.function.RequestPredicates.path;
    ...
    @Bean
    RouterFunction<ServerResponse> spaRouter() {
        ClassPathResource index = new ClassPathResource("static/index.html");
        return route().resource(path("/"), index).build();
    }
    

    That's a really simple example, fixing a problem that didn't exist (OP erased autoconfiguration that already covered it). A more realistic example would be something like this:

    import static org.springframework.web.reactive.function.server.RequestPredicates.path;
    import static org.springframework.web.reactive.function.server.RequestPredicates.pathExtension;
    import static org.springframework.web.reactive.function.server.RouterFunctions.route;
    // ...
    @Bean
    RouterFunction<ServerResponse> spaRouter() {
        ClassPathResource index = new ClassPathResource("static/index.html");
        List<String> extensions = Arrays.asList("js", "css", "ico", "png", "jpg", "gif");
        RequestPredicate spaPredicate = path("/api/**").or(path("/error")).or(pathExtension(extensions::contains)).negate();
        return route().resource(spaPredicate, index).build();;
    }
    

    It filters out requests for api or error output, and also for common static filenames, and directs all other requests that are not handled elsewhere to the home page. That's a common scenario that isn't handled by autoconfiguration.