Search code examples
springspring-bootthymeleaf

Automatically finding Thymeleaf templates with Spring Boot


How can I get Spring Boot and Thymeleaf to automatically find and map template files to be processed when accessed by the browser?

  • src/main/resources/templates/index.xhtml
  • src/main/resources/templates/bar.xhtml
  • src/main/resources/application.properties contains spring.thymeleaf.suffix=.xhtml
  • FooController.java contains @RequestMapping("/foo") and a @PostMapping method that returns bar

If I enter http://localhost:8080/ in the browser, Thymeleaf processes and displays the index.xhtml page with no extra configuration needed. But http://localhost:8080/index, http://localhost:8080/index.xhtml, and http://localhost:8080/index.html all result in 404 Not Found.

My index view does a POST to foo; FooController is activated and returns bar; and Thymeleaf processes and shows bar.xhtml, even though bar.xhtml isn't mapped anywhere in the configuration. Yet accessing http://localhost:8080/bar, http://localhost:8080/bar.xhtml, and http://localhost:8080/bar.html in a browser all result in 404 Not Found.

  • Why does GET http://localhost:8080/ process the index.xhtml template, but GET http://localhost:8080/index does not?
  • How can Thymleaf use bar as a view, but I cannot access http://localhost:8080/bar directly?
  • How can I configure Thymeleaf so that I can add src/main/resources/templates/example.xhtml and have it processed automatically as a template that I can access via http://localhost:8080/example in the browser, with no explicit configuration specifically for the example.xhtml file?

If I absolutely have to configure controllers (see my answer below), is there a way that I can at least do this in some declarative file, outside of my code?


Solution

  • As noted in Spring in Action, Fifth Edition, I can do something like this in a @Configuration class that implements WebMvcConfigurer

    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
      registry.addViewController("/bar");
    }
    

    That will allow me to process bar.xhtml automatically. (I presume there is some default configuration registry.addViewController("/").setViewName("index"), which is why my index.xhtml file is getting processed by accessing the root path.

    And I can even use the following to automatically pick up any template:

    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
      registry.addViewController("/**");
    }
    

    Unfortunately this removes the mapping from / to /index, and also prevents accessing any static resources from src/main/resources. I'm not sure how to tell Thymeleaf to use a template if it can, and fall back to a static file if not.