[JAVA] Use Thymeleaf text template mode from Spring Boot

Introduction

Thymeleaf was originally a template engine for Web pages (HTML) and specialized in HTML output, but from Thymeleaf 3 series, plain text can also be output. This can also be used as a template for posting to emails and chats.

Preparation

In this article, we will prepare a text output as standard with minimal Spring Boot using maven. The dependent libraries are different between SpringBoot 2 series and 1 series. When creating a project, please use the IDE that can use SpringToolsSuite or maven. pom.xml is introduced at the end of the article.

Text mode settings

Make settings to run Thymeleaf in text mode via Spring. Thymeleaf templates are handled from a class that inherits the TemplateEngine interface. Since we will handle from Spring Boot this time, we will use SpringTemplateEngine for Spring.

ThymeleafConfig.java


package com.github.apz.springsample.config;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;    //SpringBoot1 series is import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Configuration
public class ThymeleafConfig implements ApplicationContextAware, EnvironmentAware {
	@Bean
	public TemplateEngine textTemplateEngine() {
		final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
		templateEngine.addTemplateResolver(textTemplateResolver());
		templateEngine.setTemplateEngineMessageSource(textMessageSource());
		return templateEngine;
	}

	private ITemplateResolver textTemplateResolver() {
		final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
		templateResolver.setOrder(Integer.valueOf(1));
		templateResolver.setPrefix("/mail/");
		templateResolver.setSuffix(".txt");
		templateResolver.setTemplateMode(TemplateMode.TEXT);
		templateResolver.setCharacterEncoding("utf-8");
		templateResolver.setCacheable(false);
		return templateResolver;
	}

	@Bean
	public ResourceBundleMessageSource textMessageSource() {
		final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		messageSource.setBasename("mail/Messages");
		return messageSource;
	}

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}

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

	private ApplicationContext applicationContext;
	private Environment environment;
}

To run TemplateEngine, TemplateResolver, which controls the loading settings of template files, is required. You can also pass the MessageSource handled by Spring so that you can output the message from the message definition property.

By writing this class, Spring can be referenced by the name of textTemplateEngine, and the text template will be used with the contents of TemplateResolver defined this time. Pay particular attention to the following settings in Template Resolver.

//Template file placement directory (src/main/resources/templates/The following directories)
templateResolver.setPrefix("/mail/");

//Template file extension. Only the value set here will be read
templateResolver.setSuffix(".txt");

//Thymeleaf template mode. Since it is a text output, specify TEXT
templateResolver.setTemplateMode(TemplateMode.TEXT);

//Character encoding of the template file to be read
templateResolver.setCharacterEncoding("utf-8");

Actual output

Now that the settings are complete, the next class is to output.

package com.github.apz.springsample.component;

import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Component
@RequiredArgsConstructor  // ※
@Log4j2                   // ※
public class ThymeleafText {
	private final TemplateEngine templateEngine;

	public void process() {
		final Context ctx = new Context(Locale.getDefault());
		ctx.setVariable("subscriptionDate", new Date());		
		String text = this.templateEngine.process("/mail/sample.txt", ctx);

		log.info(text);
	}
}

To output from the Thymeleaf template engine, complete the following steps.

  1. Create a Thymeleaf Context instance
  2. Put the variables used in the Thymeleaf template in Context
  3. Just pass the template and context to load to the template engine and run the process

Startup class

Create a boot class for SpringBoot and try it out.

package com.github.apz.springsample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

import com.github.apz.springsample.component.ThymeleafText;

@SpringBootApplication
public class SpringThymeleaf3TextApplication implements CommandLineRunner {

	@Autowired
	private ThymeleafText thymeleafText;

	public static void main(String[] args) {
		new SpringApplicationBuilder(SpringThymeleaf3TextApplication.class).web(false).run(args);
	}

	@Override
	public void run(String... args) throws Exception {
		thymeleafText.process();
	}
}

Template file

This is a Thymeleaf text sample.
[# th:if=${display}]======
When display is true[# th:utext="${#dates.format(subscriptionDate, 'dd/MMM/yyyy HH:mm')}" /]It shows.
======
[/]It is the end.

Thymeleaf in text mode treats [# th: attribute name] as a tag. Other than that, the standard functions of Thymeleaf can be used as they are except for a small part.

The execution result will be as follows. (Log4J2 output is omitted)

This is a Thymeleaf text sample.
======
11 when display is true/7/2018 07:32 is displayed.
======
It is the end.

That's it (・ ω ・)

Appendix

References

Tutorial: Using Thymeleaf (ja) Tutorial: Thymeleaf + Spring

Sample code

https://github.com/A-pZ/spring-thymelaf3-text

pom.xml (SpringBoot2 series)

<?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.github.a-pz.sample</groupId>
	<artifactId>spring-thymeleaf3-text</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-thymeleaf3-text</name>
	<description>spring-thymeleaf-text-sample</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.11.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.11.0</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

pom.xml (SpringBoot1 series)

SpringBoot1 series defaults to Thymeleaf2 series, so specify 3 series and add the necessary plug-ins.

<?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.github.a-pz.sample</groupId>
	<artifactId>spring-thymeleaf3-text</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-thymeleaf3-text</name>
	<description>spring-thymeleaf-text-sample</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.14.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.11.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.11.0</version>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf</artifactId>
			<version>3.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring4</artifactId>
			<version>3.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>nz.net.ultraq.thymeleaf</groupId>
			<artifactId>thymeleaf-layout-dialect</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Recommended Posts

Use Thymeleaf text template mode from Spring Boot
Try Spring Boot from 0 to 100.
[Java] Thymeleaf Basic (Spring Boot)
Spring Boot + Springfox springfox-boot-starter 3.0.0 Use
Use Spring JDBC with Spring Boot
Use thymeleaf3 with parent without specifying spring-boot-starter-parent in Spring Boot
Use Basic Authentication with Spring Boot
Use DBUnit for Spring Boot test
How to use ModelMapper (Spring boot)
Upgrade spring boot from 1.5 series to 2.0 series
Beginning with Spring Boot 0. Use Spring CLI
Spring Boot starting from zero Part 2
Thymeleaf usage notes in Spring Boot
Spring Boot starting from zero Part 1
Loosen Thymeleaf syntax checking in Spring Boot
Story when moving from Spring Boot 1.5 to 2.1
Changes when migrating from Spring Boot 1.5 to Spring Boot 2.0
Use DynamoDB query method in Spring Boot
Changes when migrating from Spring Boot 2.0 to Spring Boot 2.2
Implement CRUD with Spring Boot + Thymeleaf + MySQL
Implement paging function with Spring Boot + Thymeleaf
Spring Boot + Thymeleaf BootStrap installation method memo
Use cache with EhCashe 2.x with Spring Boot
Run WEB application with Spring Boot + Thymeleaf
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
Hello world! With Spring Boot (Marven + text editor)
How to use Spring Boot session attributes (@SessionAttributes)
Use Servlet filter in Spring Boot [Spring Boot 1.x, 2.x compatible]
Create CRUD apps with Spring Boot 2 + Thymeleaf + MyBatis
Create your own Utility with Thymeleaf with Spring Boot
◆ Get API created by Spring Boot from React
Challenge Spring Boot
Spring Boot Form
Spring Boot Memorandum
gae + spring boot
If you want to separate Spring Boot + Thymeleaf processing
Customizer for Platform Transaction Manager added from Spring Boot 1.5
[Introduction to Spring Boot] Submit a form using thymeleaf
How to use CommandLineRunner in Spring Batch of Spring Boot
Load an external jar from a Spring Boot fat jar
File upload with Spring Boot (do not use Multipart File)