1. Overview

In this tutorial, we'll see how we can define multiple template locations using Thymeleaf in a Spring Boot application.

2. Maven Dependencies

Firstly, we'll add the spring-boot-starter-web and spring-boot-starter-thymeleaf Maven dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>

3. Default Configuration

By default, Thymeleaf will look for the templates in the templates/ directory on the classpath.

Though we can configure this location with the spring.thymeleaf.prefix property in application.properties:

spring.thymeleaf.prefix=classpath:/templates/

Now, we'll create a controller to investigate the template path resolution in detail.

@Controller
public class TemplateLocationController {

    @RequestMapping("/welcome")
    public String sayWelcome() {
        return "welcome";
    }
}

Here, we have the TemplateLocationController class which has a single endpoint. Since this endpoint returns welcome as the template name and the prefix is classpath:/templates/, the final path becomes classpath:/templates/welcome.html. During the development time, this template resides at src/main/resources/templates/welcome.html - if we use the default Maven folder structure.

4. Defining Multiple Locations

To define multiple template locations, we must define several Spring beans implementing the ITemplateResolver interface. Thymeleaf provides several implementation classes of ITemplateResolver like SpringResourceTemplateResolver and ClassLoaderTemplateResolver:

@Configuration
public class TemplateResolverConfiguration {

    @Bean
    public SpringResourceTemplateResolver firstTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setPrefix("classpath:/templates/templatelocation/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setOrder(0);
        templateResolver.setCheckExistence(true);

        return templateResolver;
    }

    @Bean
    public ClassLoaderTemplateResolver secondTemplateResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("templates/templatelocation/other/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setOrder(1);
        templateResolver.setCheckExistence(true);

        return templateResolver;
    }

    @Bean
    public ClassLoaderTemplateResolver thirdTemplateResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("templates/templatelocation/another/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setOrder(2);
        templateResolver.setCheckExistence(true);

        return templateResolver;
    }
}

Here, we're creating one SpringResourceTemplateResolver and two ClassLoaderTemplateResolver beans. During the initialization, we're assigning different paths using the setPrefix method. Additionally, we're defining the order of the beans using the setOrder method.

As a result, when a controller method returns a view name, Thymeleaf will look for it in four different locations respectively: /templates/templatelocation//templates/templatelocation/other/, /templates/templatelocation/another/ and/templates/.

5. Summary

In this tutorial, we've looked at how we can define multiple template locations using Thymeleaf in a Spring Boot application.

Finally, check out the source code for all examples over on Github.