はじめに
Thymeleafは本来Webページ(HTML)用のテンプレートエンジンで、HTMLの出力に特化したものでしたが、Thymeleaf3系からは、プレーンテキストも出力できます。これによりメールやチャットへの投稿用テンプレートにも使えます。
前準備
本記事ではmavenを使った最小限のSpringBootで、テキストを標準出力するものを用意します。SpringBoot2系と1系とで、依存関係にあるライブラリが異なります。プロジェクト作成の際には、SpringToolsSuiteないしはmavenが利用できるIDEをお使いください。pom.xmlは記事の最後に紹介しています。
テキストモードの設定
テキストモードでThymeleafを動かすための設定を、Spring経由で行います。
Thymeleafのテンプレートは TemplateEngine インタフェースを継承したクラスから扱います。今回はSpringBootから扱うので、Spring用の SpringTemplateEngine を用います。
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系は、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;
}
TemplateEngineを動かすには、テンプレートファイルの読み込み設定を司る TemplateResolver が必須です。さらにメッセージ定義プロパティからメッセージを出力できるよう、Springで扱っているMessageSource も渡せます。
このクラスの記述により、Springは textTemplateEngine の名前で参照でき、今回定義したTemplateResolverの内容でテキストテンプレートを使います。TemplateResolverでは特に以下の設定に注視してください。
// テンプレートファイルの配置ディレクトリ(src/main/resources/templates/ 以下のディレクトリ)
templateResolver.setPrefix("/mail/");
// テンプレートファイルの拡張子。ここに設定された値以外は読み込まなくなる
templateResolver.setSuffix(".txt");
// Thymeleafのテンプレートモード。テキスト出力なので、TEXTを指定
templateResolver.setTemplateMode(TemplateMode.TEXT);
// 読み込むテンプレートファイルの文字エンコード
templateResolver.setCharacterEncoding("utf-8");
実際に出力する
設定が完了したので、次は出力するクラスです。
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);
}
}
※RequiredArgsConstructorとLog4j2はproject Lombokのアノテーションです。
Thymeleafテンプレートエンジンから出力するには、以下のステップで完了です。
- ThymeleafのContextインスタンスを作り
- Thymeleafのテンプレート内で使う変数をContextに入れ
- テンプレートエンジンに、読み込むテンプレートとコンテキストを渡して processを実行するだけです
起動クラス
SpringBootの起動クラスを作って、動作をしてみます。
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();
}
}
テンプレートファイル
これはThymeleafテキストサンプルです。
[# th:if=${display}]======
displayがtrueのときは[# th:utext="${#dates.format(subscriptionDate, 'dd/MMM/yyyy HH:mm')}" /]表示されます。
======
[/]末尾です。
テキストモードのThymeleafは、[# th:属性名] をタグとして扱います。それ以外はThymeleafの標準機能がごく一部を除きそのまま使えます。
実行結果は次のようになるでしょう。(Log4J2の出力は省略しています)
これはThymeleafテキストサンプルです。
======
displayがtrueのときは11/7/2018 07:32表示されます。
======
末尾です。
以上です(・ω・)
Appendix
参考文献
Tutorial: Using Thymeleaf (ja)
Tutorial: Thymeleaf + Spring
サンプルコード
https://github.com/A-pZ/spring-thymelaf3-text
pom.xml (SpringBoot2系)
<?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系)
SpringBoot1系は、デフォルトはThymeleaf2系になってしまうので、3系を指定し、さらに必要なプラグインを追加します。
<?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>