Spring Boot Thymeleaf Configuration Example
This tutorial demonstrates how to configure Spring Boot and Thymeleaf. We are creating a simple Spring Boot Thymeleaf Example. In this example we configure Spring Boot using application.yml
file and place the Thymeleaf templates in the src/main/resources/templates
folder. We also utilise org.webjars
to load static resources like bootstrap
and jquery
.
Project Structure
Let’s start by looking at the project structure.
Maven Dependencies
We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on the class-path. By default spring-boot
uses thymeleaf version 2. We can change this by overwriting the thymeleaf.version
and thymeleaf-layout-dialect.version
maven properties. Note: we also use org.webjars
to load bootstrap
and jquery
.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.spring.mvc</groupId>
<artifactId>thymeleaf</artifactId>
<version>1.0.0-SNAPSHOT</version>
<url>http://memorynotfound.com</url>
<name>Spring MVC - ${project.artifactId}</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<thymeleaf.version>3.0.8.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- webjar bootstrap and jquery dependencies -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot
We use spring boot to bootstrap our application. The @SpringBootApplication
triggers the EnableAutoConfiguration
and ComponentScan
. This is a convenience annotation that is equivalent to declaring @Configuration
, @EnableAutoConfiguration
and @Configuration
.
package com.memorynotfound.thymeleaf;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String... args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Adding Model Attributes in Spring Controller
On application boot time, the message.home
property is loaded from the application.yml
file. We add this property to the Model
which’ll be available to use in the thymeleaf template.
package com.memorynotfound.thymeleaf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
private static final Logger log = LoggerFactory.getLogger(HomeController.class);
@Value("${messages.home:default-value}")
private String message = "Hello World";
@RequestMapping("/")
public String welcome(Model model) {
log.info("Spring Boot Thymeleaf Configuration Example");
model.addAttribute("message", message);
return "home";
}
}
Configure Spring boot and Thymeleaf
We configure spring-boot
and thymeleaf
using the application.yml
file located in the src/main/resources
folder.
spring.thymeleaf.cache
– enable/disable template caching.spring.thymeleaf.check-template
– check that the template exists before rendering it.spring.thymeleaf.check-template-location
– check that the templates location exists.spring.thymeleaf.content-type
– specifies content-type value.spring.thymeleaf.enabled
– enable mvc thymeleaf view resolution.spring.thymeleaf.encoding
– specifies template encoding.spring.thymeleaf.excluded-view-names
– comma-separated list of view names that should be excluded from resolution.spring.thymeleaf.mode
– template mode to be applied to templates. See alsoStandardTemplateModeHandlers
.spring.thymeleaf.prefix
– specifies the prefix that gets prepended to view names when building a URL.spring.thymeleaf.suffix
– specifies the suffix that gets appended to view names when building a URL.spring.thymeleaf.template-resolver-order
– specifies the order of the template resolver in the chain.spring.thymeleaf.view-names
– comma-separated list of view names that can be resolved.
server:
port: ${PORT:8081}
messages:
home: Hello, Memorynotfound!
spring:
thymeleaf:
cache: false
check-template: true
check-template-location: true
content-type: text/html
enabled: true
encoding: UTF-8
# excluded-view-names:
# mode: HTML5
# prefix: /templates/
# suffix: .html
# template-resolver-order:
# view-names:
logging:
level:
- ".=info"
- "com.memorynotfound=debug"
- "org.springframework=info"
Creating Thymeleaf Template
This is an example thymeleaf template named: home.html
. Located in the src/main/resources/templates
folder.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
<link rel="stylesheet" th:href="@{/css/main.css}"/>
<title>Getting Started: Serving Web Content</title>
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">
<img th:src="@{/img/logo.png}" alt="memorynotfound logo"/>
</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="starter-template">
<h1>Spring Boot Thymeleaf Configuration Example</h1>
<h2 th:text="${message}"></h2>
</div>
</div>
<!-- include javascript -->
<script type="text/javascript" src="webjars/jquery/3.2.1/jquery.min.js/"></script>
<script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
The main.css
file located in the src/main/resources/static/css
folder.
h1 {
color: #78ab46;
}
h2 {
color: #2189ce
}
Run Spring Boot application
When we run the spring boot application we receive the following output.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.8.RELEASE)
2017-10-30 11:56:53.989 INFO 61616 --- [ main] c.memorynotfound.thymeleaf.Application : Starting Application on darwin-13.local with PID 61616 (/Users/camelcode/Documents/projects/memorynotfound/tutorials/java/spring/spring-mvc/thymeleaf/target/classes started by camelcode in /Users/camelcode/Documents/projects/memorynotfound/tutorials/java)
2017-10-30 11:56:53.994 INFO 61616 --- [ main] c.memorynotfound.thymeleaf.Application : No active profile set, falling back to default profiles: default
2017-10-30 11:56:54.819 INFO 61616 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@72bc6553: startup date [Mon Oct 30 11:56:54 CET 2017]; root of context hierarchy
2017-10-30 11:56:57.134 INFO 61616 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8081 (http)
2017-10-30 11:56:57.154 INFO 61616 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2017-10-30 11:56:57.158 INFO 61616 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23
2017-10-30 11:56:57.333 INFO 61616 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2017-10-30 11:56:57.333 INFO 61616 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2519 ms
2017-10-30 11:56:57.567 INFO 61616 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2017-10-30 11:56:57.573 INFO 61616 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-10-30 11:56:57.574 INFO 61616 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-10-30 11:56:57.574 INFO 61616 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-10-30 11:56:57.575 INFO 61616 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2017-10-30 11:56:58.206 INFO 61616 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@72bc6553: startup date [Mon Oct 30 11:56:54 CET 2017]; root of context hierarchy
2017-10-30 11:56:58.349 INFO 61616 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.memorynotfound.thymeleaf.HomeController.welcome(org.springframework.ui.Model)
2017-10-30 11:56:58.354 INFO 61616 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-10-30 11:56:58.354 INFO 61616 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-10-30 11:56:58.403 INFO 61616 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-30 11:56:58.404 INFO 61616 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-30 11:56:58.511 INFO 61616 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-30 11:56:58.604 WARN 61616 --- [ main] org.thymeleaf.templatemode.TemplateMode : [THYMELEAF][main] Template Mode 'HTML5' is deprecated. Using Template Mode 'HTML' instead.
2017-10-30 11:56:59.532 INFO 61616 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-10-30 11:56:59.618 INFO 61616 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8081 (http)
2017-10-30 11:56:59.628 INFO 61616 --- [ main] c.memorynotfound.thymeleaf.Application : Started Application in 6.81 seconds (JVM running for 7.715)
2017-10-30 11:57:40.789 INFO 61616 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-10-30 11:57:40.790 INFO 61616 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-10-30 11:57:40.811 INFO 61616 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 21 ms
2017-10-30 11:57:40.844 INFO 61616 --- [nio-8081-exec-1] c.m.thymeleaf.HomeController : Spring Boot Thymeleaf Configuration Example
Example Output
The generated spring boot thymeleaf template looks like this.
References
- Thymeleaf Official Website
- Thymeleaf 3.0 Documentation
- Spring Boot Loading Static Content
- Adding Static Resources Thymeleaf