Spring Boot 2 Maven Directory View Resolver

Viewed 351

I currently have a Spring Boot application that is using React JS for the front end. I'm running inside Visual Studio, and via webpack, I'm compiling resources and outputting them to a Maven target folder. You can see the structure of the directory with the Java classes sitting inside the 'classes' folder and the client application sitting now inside the webapp folder - notice the index.html.

As this is a single page application I only need this page to resolve. As such my controller is configured to return the index file.

@SpringBootApplication
public class AdminApplication 
{

   public static void main( String[] args )
   {
      SpringApplication.run( AdminApplication.class, args );
   }

}

@Controller
public class DefaultController
{


   @RequestMapping( "/**" )
   public ModelAndView reactApp()
   {
      return new ModelAndView( "index" );
   }
}

Now. My problem comes with telling my view resolver to talk to this directory.

As you can see from the commented code, I've tried only a couple of hundred options for trying to get it to resolve the view. I've got the full file path to my project directory available on the documentRoot so if necessary and thought potentially I would need that.

I've put a breakpoint in the controller and this definitely does get hit, it just returns a 404 when trying to find the relevant view each time. Any guidance on what my viewResolver might need to look like appreciated. I can see there's a couple of Classes that may or may not be correct:

e.g. SpringResourceTemplateResolver and ClassLoaderTemplateResolver - not sure on which of these is most relevant for my requirements

@EnableWebMvc
@Configuration
public class MvcConfig implements WebMvcConfigurer,ApplicationContextAware {

   private ApplicationContext context;

   @Value("${server.document-root:}")
   private String documentRoot;

   @Override
   public void setApplicationContext(  ApplicationContext applicationContext )  {
      this.context = applicationContext;
   }


   // private ITemplateResolver htmlTemplateResolver() {
   // SpringResourceTemplateResolver resolver = new
   // SpringResourceTemplateResolver();
   // resolver.setApplicationContext(applicationContext);
   // resolver.setPrefix(documentRoot);
   // resolver.setCacheable(false);
   // resolver.setTemplateMode(TemplateMode.HTML);
   // return resolver;
   // }




   // @Bean
   // public SpringResourceTemplateResolver templateResolver() {
   // SpringResourceTemplateResolver templateResolver = new
   // SpringResourceTemplateResolver();
   // templateResolver.setPrefix( "/webapp/" );
   // templateResolver.setCacheable(false);
   // templateResolver.setSuffix(".html");
   // templateResolver.setTemplateMode("HTML");
   // return templateResolver;
   // }
   private ITemplateResolver templateResolver() {
      SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
      resolver.setApplicationContext(context);
      resolver.setPrefix("templates/");
      resolver.setSuffix(".html");
      resolver.setTemplateMode(TemplateMode.HTML);
      return resolver;
    }


   //  public ITemplateResolver templateResolver() {

   //    ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();

   //       templateResolver.setPrefix("templates/");
   //       templateResolver.setCacheable(false);
   //       templateResolver.setSuffix(".html");
   //       templateResolver.setTemplateMode(TemplateMode.HTML);
   //       templateResolver.setCharacterEncoding("UTF-8");

   //       return templateResolver;
   // }


}

enter image description here

enter image description here

3 Answers

you don't need MvcConfig

just set the static-locations property in src/main/resources/application.properties to spring.resources.static-locations=classpath:/webapp/

map all possible request to your index-page like:

@GetMapping({"/index","/","/home"})
public String reactApp()
   {
      return "/index.html";
   }

optional you could redirect the requests to your index-page

@GetMapping({"/index","/","/home"})
public String reactApp()
   {
      return "redirect:/index.html";
   }

You don't need the MvcConfig class, Spring boot auto-configure the view resolver. All you have to do is to put your templates to the src/main/resources/templates/ directory and make a simple controller mapping like this

@RequestMapping(value = "/")
public String index() {
    return "index";
}

in your home controller. You can also check out this React.js and Spring example

you will need to configure your resource handler, that way:

@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/**")
                .addResourceLocations("file:/path/to/dir/webapp/");
    }
}

Notice, that in unix you will use file:/ and for windows file:///C:/path/to/dir/webapp/

And then redirect the/ to index.html

@RequestMapping
@RestController
public class IndexEndpoint {
    @GetMapping("/")
    public String reactApp() {
        return "/index.html";
    }
}

I have tested it on a MacOS and it worked prefect.

Related