LoginSignup
11
14

More than 5 years have passed since last update.

SpringBootからThymeleafのテキストテンプレートモードを使う

Posted at

はじめに

Thymeleafは本来Webページ(HTML)用のテンプレートエンジンで、HTMLの出力に特化したものでしたが、Thymeleaf3系からは、プレーンテキストも出力できます。これによりメールやチャットへの投稿用テンプレートにも使えます。

前準備

本記事ではmavenを使った最小限のSpringBootで、テキストを標準出力するものを用意します。SpringBoot2系と1系とで、依存関係にあるライブラリが異なります。プロジェクト作成の際には、SpringToolsSuiteないしはmavenが利用できるIDEをお使いください。pom.xmlは記事の最後に紹介しています。

テキストモードの設定

テキストモードでThymeleafを動かすための設定を、Spring経由で行います。
Thymeleafのテンプレートは TemplateEngine インタフェースを継承したクラスから扱います。今回はSpringBootから扱うので、Spring用の SpringTemplateEngine を用います。

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系は、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テンプレートエンジンから出力するには、以下のステップで完了です。

  1. ThymeleafのContextインスタンスを作り
  2. Thymeleafのテンプレート内で使う変数をContextに入れ
  3. テンプレートエンジンに、読み込むテンプレートとコンテキストを渡して 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>
11
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14