Shoham
Shoham

Reputation: 7294

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.

Upvotes: 176

Views: 283697

Answers (13)

Abdelrahman Elattar
Abdelrahman Elattar

Reputation: 560

Simply you have to create new class and add annotation @Controller used to define a controller that returns view names. The view names are resolved by a ViewResolver to render the actual view (e.g., an HTML page). It is typically used in web applications that serve dynamic content.

Add you index.html file under src/main/resources/static

@Controller
public class TestController {

    @GetMapping("/")
    public String getHome() {
        return "index";
    }
}

Upvotes: 0

ethan
ethan

Reputation: 1

To implement nginx-like functionality in spring boot, you can refer to the following code, which is my final solution.

this is without context-path

    @Configuration
public class UiConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/", "classpath:/templates/")
// To solve the 404 problem of browser refresh
// Customize the ClassPathResource implementation class to force the use of the **index.html** resource when the address requested by the front-end does not match the corresponding path
// you can check the implementation from {@link ResourceHttpRequestHandler#resolveResourceLocations}
                .addResourceLocations(new ClassPathResource("/static/index.html") {
                    @Override
                    public Resource createRelative(String relativePath) {
                        return this;
                    }
                });
    }

}

if you have context-path for you html, you can change it accordingly.


@Configuration
public class UiConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/admin-ui/**", "/admin-ui/", "/admin-ui")
                .addResourceLocations("classpath:/admin-ui/")
                .addResourceLocations(new ClassPathResource("/admin-ui/index.html") {
                    @Override
                    public Resource createRelative(String relativePath) {
                        return this;
                    }
                })
        ;
    }

}

Upvotes: 0

Alex
Alex

Reputation: 1

I struggled with this for an hour, trying various solutions that did not work, before I realised that the problem was I hadn't included "/" in requestMatchers().permitAll() in the securityConfig.

Upvotes: 0

Dave Syer
Dave Syer

Reputation: 58094

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.

Upvotes: 181

justin
justin

Reputation: 3607

An example of Dave Syer's answer and comment:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebMvcConfig {

    @Bean
    public WebMvcConfigurerAdapter forwardToIndex() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                // forward requests to /admin and /user to their index.html
                registry.addViewController("/admin").setViewName(
                        "forward:/admin/index.html");
                registry.addViewController("/user").setViewName(
                        "forward:/user/index.html");
            }
        };
    }

}

Upvotes: 46

zappee
zappee

Reputation: 22688

If you use the latest spring-boot 2.1.6.RELEASE with a simple @RestController annotation then you do not need to do anything, just add your index.html file under the resources/static folder:

project
  ├── src
      ├── main
          └── resources
              └── static
                  └── index.html

Then hit the root URL of your app http://localhost:8080.

The solution above works out of the box with Spring and Tomcat and your HTTP request to the root / is mapped automatically to the index.html file. But if you used @EnableWebMvc annotation then you switch off that Spring Boot does for you. In this case, you have two options:

(1) remove that annotation

(2) or you could add back the view controller that you switched off

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

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

Hope that it will help everyone.

Upvotes: 25

Neeraj Gahlawat
Neeraj Gahlawat

Reputation: 1679

You can add a RedirectViewController like:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController("/", "/index.html");
    }
}

Upvotes: 7

dev_fondue
dev_fondue

Reputation: 121

I had the same problem. Spring boot knows where static html files are located.

  1. Add index.html into resources/static folder
  2. Then delete full controller method for root path like @RequestMapping("/") etc
  3. Run app and check http://localhost:8080 (Should work)

Upvotes: 5

sampathlk
sampathlk

Reputation: 338

Update: Jan-2019

First create public folder under resources and create index.html file. Use WebMvcConfigurer instead of WebMvcConfigurerAdapter.

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebAppConfig implements WebMvcConfigurer {

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

}

Upvotes: 13

ArifMustafa
ArifMustafa

Reputation: 4955

Inside Spring Boot, I always put the webpages inside a folder like public or webapps or views and place it inside src/main/resources directory as you can see in application.properties also.

Spring_Boot-Project-Explorer-View

and this is my application.properties:

server.port=15800
spring.mvc.view.prefix=/public/
spring.mvc.view.suffix=.html
spring.datasource.url=jdbc:mysql://localhost:3306/hibernatedb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.format_sql = true

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

as soon you put the url like servername:15800 and this request received by Spring Boot occupied Servlet dispatcher it will exactly search the index.html and this name will in case sensitive as the spring.mvc.view.suffix which would be html, jsp, htm etc.

Hope it would help manyone.

Upvotes: 6

Pravind Kumar
Pravind Kumar

Reputation: 911

  1. index.html file should come under below location - src/resources/public/index.html OR src/resources/static/index.html if both location defined then which first occur index.html will call from that directory.
  2. The source code looks like -

    package com.bluestone.pms.app.boot; 
    import org.springframework.boot.Banner;
    import org.springframework.boot.Banner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    import org.springframework.context.annotation.ComponentScan;
    
    
    
    @SpringBootApplication 
    @EnableAutoConfiguration
    @ComponentScan(basePackages = {"com.your.pkg"}) 
    public class BootApplication extends SpringBootServletInitializer {
    
    
    
    /**
     * @param args Arguments
    */
    public static void main(String[] args) {
    SpringApplication application = new SpringApplication(BootApplication.class);
    /* Setting Boot banner off default value is true */
    application.setBannerMode(Banner.Mode.OFF);
    application.run(args);
    }
    
    /**
      * @param builder a builder for the application context
      * @return the application builder
      * @see SpringApplicationBuilder
     */
     @Override
     protected SpringApplicationBuilder configure(SpringApplicationBuilder 
      builder) {
        return super.configure(builder);
       }
    }
    

Upvotes: 3

Rodrigo Ribeiro
Rodrigo Ribeiro

Reputation: 269

@Configuration  
@EnableWebMvc  
public class WebAppConfig extends WebMvcConfigurerAdapter {  

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController("/", "index.html");
    }

}

Upvotes: 18

Krish
Krish

Reputation: 824

if it is a Spring boot App.

Spring Boot automatically detects index.html in public/static/webapp folder. If you have written any controller @Requestmapping("/") it will override the default feature and it will not show the index.html unless you type localhost:8080/index.html

Upvotes: 35

Related Questions