Thymeleafとは?基本構文・Spring Bootでの使い方を解説
2023.11.18

Spring Bootを利用する際、画面表示で使うのが「Thymeleaf」です。
なぜThymeleafをつかうのか、JSPとはどう違うのか?といった疑問にお答えします。


1.Thymeleafとは?


まずは、Thymeleafとはどんなものなのかについて解説していきます。

①拡張性の高いテンプレートエンジン

テンプレートエンジンとは、「テンプレート(枠組み)」とデータを組み合わせて画面表示を構成する仕組みです。


Webアプリにおける「テンプレート」は主に画面デザインを指し、その画面デザインとデータを組み合わせることで画面に表示する内容を生成します。

テンプレートエンジンの概要図

Thymeleafは高い拡張性を持つテンプレートエンジンであり、特定のテンプレートを処理するだけでなく、独自の機能の追加もできます。


例えば、テキストを表示する際の機能を拡張することで、日付型のデータを表示する場合に、自動で「令和4年10月20日」のような和暦で表示できるのです。


テンプレートに表示するデータをそのまま表示するだけでなく、独自の加工をしたい場合に便利に利用できると覚えましょう。

②Thymeleafで処理できるテンプレート

Thymeleafは様々なテンプレートに対応しており、以下のようなファイル形式に対応しています。


・HTML

・XML

・テキスト

・JavaScript

・CSS

Spring Bootと組み合わせて使用する場合、HTMLをテンプレートとして使用します。

③Spring Bootで使用が推奨されている

Spring Bootでは、JSPの利用も可能ですが、Thymeleafによるテンプレートエンジンを推奨しています。


これは、Spring Bootの構成がMVCに基づいていることに関係しています。

MVCとは、Webの処理をModel-View-Controllerの3つに分けてファイルを構成する方法です。


MVCについての詳しい説明は、以下の記事を参考にしてみてください。

【5分でわかる】Spring MVC入門! Bootとの違いや特徴、サンプルまで解説!

UserとModel、View、Controllerの関係図

Spring Bootは、ModelとControllerに相当する処理を有していますが、Viewに相当する処理を持っていません。
そこで、テンプレートエンジンであるThymeleafを利用するのです。

ThymeleafはJSPと比べると不便?

実は、Thymeleafには表示に関する処理しか記述できません。
そのため、JSPと比べるとできることが少ないという点はデメリットともとれます。


JSPをMVCのViewとして利用する場合、自由にJavaのコードをファイル内に記載できてしまいます。


この「処理を記述できる」ということは、一見メリットにも見えるでしょう。
しかしながら、Viewの責務は入出力やボタン操作、デザインの変更といった表示に関する処理のみを記述する決まりになっています。


そのため、処理の記載に制限のあるThymeleafを採用することで、MVCに沿った構成で開発できることを覚えておきましょう。


2.Thymeleafの基本的な構文


Thymeleafの概要を理解したところで、次は基本的な構文を解説します。

①リテラル

リテラルとは、テンプレート内に記載した固定値を指します。

たとえば、リテラルとして文字列や数値を表示したい場合には以下のように記述します。

<p>
<span th:text="'Hello, World'"></span>
<span th:text="123"></span>
</p>

文字列の場合には、シングルクォート(’)で囲むのを忘れないようにしましょう。

こうすることで、最終的に以下のようなHTMLが生成されます。

<p>
<span>Hello, World</span>
<span>123</span>
</p>

②文字列連結

文字列は、Java同様に「+」を使うことで連結できます。

<span th:text="'Hello' + 'World'"></span>

もちろん、後述の変数と組み合わせることも可能です。

<span th:text="'Hello, ' + ${name}"></span>

③算術演算子

Javaと同様に、数値リテラルの四則演算が可能です。

<div>
    <p th:text="20 + 5"></p>
    <p th:text="20 - 5"></p>
    <p th:text="20 * 5"></p>
    <p th:text="20 / 5"></p>
    <p th:text="20 % 5"></p>
</div>

④条件演算子

条件に応じて値を変更する場合には、条件演算子を利用することで容易に内容を変更できます。

<span th:text="${age} < 18 ? '未成年' : '成人'"></span>

⑤条件式

条件式を使うことで、表示する内容を操作できます。

<div th:if="${showFlag}">
 <p>表示されます</p>
</div>

この場合、変数「showFlag」の内容がtrueの場合には「表示されます」の文字が表示されます。

そのほか、ifだけでなくswitch文に相当する機能も利用できます。


「th:if」に対応する「th:else」の属性は存在しないため、elseに相当する処理を書きたい場合には「th:switch」を利用しましょう。

<div th:switch="${size}">
  <p th:case="small">Sサイズ</p>
  <p th:case="middle">Mサイズ</p>
  <p th:case="large">Lサイズ</p>
  <p th:case="*">オーダーメイド</p>
</div>

⑥論理演算子

条件式を設定する際、「||(OR)」または「&&(AND)」を利用することで複数の条件を指定できます。

<div th:if="${a == 2 && b != 2}">
   <p>表示されます</p>
</div>

⑦比較と等価

値を比較する方法として、「=」や「>」「<」といった等号、不等号記号を利用できます。

ただし、「<」や「>」はエスケープされてしまうので、以下のように記述する必要があります。

<div th:if="${a > 1}">
   <p>表示されます</p>
</div>

大小関係を表示したい場合には、それぞれ以下のように表示すると覚えましょう。

変換元変換先
&lt;
&gt;
<=&lt;=
>=&gt;=

⑧単純式

Thymeleafのテンプレートから、モデルに格納された値や変数を参照する場合には、単純式を利用します。

変数式

変数を宣言する場合には、以下のように${}で記述します。

<div th:text="${showFlag}">
 <p>表示されます</p>
</div>

選択変数式

モデルに格納されたオブジェクトではなく、そのオブジェクトの中に格納された変数の値を取得する場合には「$」ではなく「*」を使用します。


以下のような記述をすることで、dataオブジェクト内にある「name」変数の値を取得して表示します。

<div th:object="${data}">
  <span th:text="*{name}"></span>
</div>

メッセージ式

モデルに格納された変数ではなく、Spring Bootのメッセージ(プロパティ値など)で指定している固定値を表示する場合には、メッセージ式を利用します。


例えば、resourcesフォルダにmessages.propertiesを作成したとします。

common.hello=こんにちは!

このコード値を読み取る場合、Thymeleafでは以下のように記述します。

<p th:text="#{common.hello}"></p>

リンク式

単純式のうち、aタグなどのリンク要素と組み合わせて利用するのがリンク式です。

以下のような記載をすることで、変数を用いて動的なURLを構築できます。

<a th:href="${/user/{id}}">詳細</a>

リンク式を使用した場合、他の方式と異なり自動的にURLエンコーディングされます。
そのため、URLを構成する場合にはこのリンク式を利用すると覚えましょう。

⑨繰り返し処理

モデル内のデータを使って、動的にリストやテーブルを作成する場合にはThymeleafの繰り返し処理を使用します。

<table>
  <tr>
    <th>名前</th>
    <th>説明</th>
  </tr>
  <tr th:each="data : ${list}">
    <td th:text="${data.name}"></td>
    <td th:text="${data.description}"></td>
  </tr>
</table>




3.Spring BootでThymeleafを使ってみよう

①前提条件

Spring Bootのプロジェクトがすでに作成済みであり、MavenまたはGradleを用いてプロジェクトをビルドできる状態であることとします。

②Thymeleafを依存関係に追加

Spring Bootであれば、MavenまたはGradleを使ってプロジェクトを作成しているので、依存関係に追加するだけで利用できます。

Mavenの場合

Mavenを利用している場合、以下の依存関係をpom.xmlに追加することでThymeleafを利用できます。

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

Gradleの場合

Gradleを利用している場合、以下の依存関係をbuild.gradleのdependenciesに追加することで、Thymeleafを利用できます。

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

③コントローラーを作成

それでは、実際にSpring Bootのコントローラーを作成していきましょう。

今回は、Thymeleafに情報を表示するだけの簡単なページを作成します。

package jp.co.trainocamp.samples.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {

  @RequestMapping("/home")
  public String get(Model model) {
    
    // RequestMappingの引数にModelを指定することで、
    // テンプレートで使用するモデルに値を格納できる
    model.addAttribute("message", "Hello, Template World!");
    
    // テンプレートHTMLのファイル名を記載(拡張子は不要)
    return "home";
  }
}

④ビューを作成

つぎに、ビューとなるテンプレートとなるHTMLを作成しましょう。

テンプレートは「src/main/resources/templates」フォルダに格納するので、「src/main/resources/templates/home.html」を作成します。

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
  <div>
    <span th:text="${message}"></span>
  </div>
</body>
</html>

このテンプレートHTMLでは、メッセージを表示するためにデータを取得する変数式を追加しています。

Thymeleafのテンプレートを作る場合、通常のHTMLファイルと同じように記述しますが、以下の記述を<html>の属性に指定し忘れないように注意しましょう。

xmlns:th="http://www.thymeleaf.org"

⑤実行

それでは、実行してみましょう。

http://localhost:8080/home」にアクセスし、以下のように表示されれば完了です。

ブラウザで「http://localhost:8080/home」にアクセスした画面


4.Thymeleafの基本的な使い方


Thymeleafの基本的な使い方をマスターしたところで、実践的な画面開発の方法を紹介します。

①th:ifで条件分岐

条件に応じて表示内容を変えるには「th:if」を使用します。

今回は、値が空の場合とそうでない場合での表示を変えてみます。


▶︎コントローラー

@Controller
public class HelloController {

  /**
   * パラメータを用いたThymeleafのサンプル
   * 
   * /hello?name=XXX で指定したパラメータをもとに画面表示する
   * 
   * @param name パラメータ
   * @param model モデル情報
   * @return テンプレートのHTML
   */
  @RequestMapping("/hello")
  public String get(@RequestParam("name") @Nullable String name, Model model) {
    
    model.addAttribute("name", name);
    
    return "hello";
  }
}

▶︎テンプレートHTML(hello.html)

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>こんにちは!</title>
</head>
<body>
  <div th:if="${name} != null" >
    <span th:text="'こんにちは、' + ${name} + 'さん!'"></span>
  </div>
</body>
</html>

この状態で起動し、「http://localhost:8080/hello」にアクセスすると画面に何も表示されません。

ここで、URLをhttp://localhost:8080/hello?name=太郎

とすると、そのパラメータに応じた名前が表示されます。

ブラウザで「http://localhost:8080/hello?name=太郎」にアクセスした画面

②th:eachで繰り返し処理

データベースなどを利用したWebアプリを開発する場合に、避けては通れないのが「一覧表示」です。

データの内容からテーブルを生成する例を紹介します。


▶︎コントローラー

package jp.co.trainocamp.samples.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import jp.co.trainocamp.samples.entity.UserData;

@Controller
public class ListController {

  @RequestMapping("/list")
  public String list(Model model) {
    
    List<UserData> displayData = new ArrayList<UserData>();
    
    // サンプルとして3名のユーザーを追加
    displayData.add(new UserData("太郎", 18));
    displayData.add(new UserData("次郎", 21));
    displayData.add(new UserData("三郎", 14));
    
    model.addAttribute("users", displayData);
    
    return "list";
  }
}

▶︎モデルに格納するユーザー情報

package jp.co.trainocamp.samples.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * ユーザー情報
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserData {
  
  /** 氏名 */
  private String name;
  /** 年齢 */
  private int age;
}

▶︎テンプレートHTML(list.html)

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>一覧</title>
</head>
<body>
  <table border="1">
    <tr>
      <th>名前</th>
      <th>年齢</th>
    </tr>
    <tr th:each="user : ${users}">
      <td th:text="${user.name}"></td>
      <td th:text="${user.age}"></td>
    </tr>
  </table>
</body>
</html>

実行すると、以下のように3名のユーザー情報が表示されます。

ブラウザで「http://localhost:8080/list」にアクセスした画面

③フォーム入力

ThymeleafとSpring Bootを組み合わせることで、ユーザーが情報を入力するフォームも簡単に作成できます。

データを送信する画面を作ってみましょう。


▶︎コントローラー

package jp.co.trainocamp.samples.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import jp.co.trainocamp.samples.entity.UserData;

@Controller
public class AddController {

  @GetMapping("/add")
  public String get(Model model) {
    
    // 初期表示として、空のデータを表示する
    model.addAttribute("userData", new UserData());
    
    return "add";
  }
  
  @PostMapping("/add")
  public String post(UserData userData, Model model) {
    
    System.out.println(String.format("%s is %d", userData.getName(), userData.getAge()));
    
    return "add";
  }
}

▶︎テンプレートHTML(add.html)

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>こんにちは!</title>
</head>
<body>
  <form th:action="@{/add}" method="POST" th:object="${userData}">  
    <p>
      <input type="text" name="name" th:value="*{name}" placeholder="氏名" />
    </p>
    <p>
      <input type="number" name="age" th:value="*{age}" placeholder="年齢" />
    </p>
    <input type="submit" value="送信" />
  </form>
</body>
</html>

これを起動すると以下のような画面が表示されます。

ブラウザで「http://localhost:8080/add」にアクセスした画面

以下のように入力して送信ボタンを押下します。

ブラウザで「http://localhost:8080/list」にアクセスし、「佐藤 太郎」「19」を入力した画面

データが正常に送信されると、サーバーのコンソールに以下のように出力されるので確認しましょう。

佐藤 太郎 is 19

④チェックボックス

Thymeleafでチェックボックスを利用する場合には、少しテクニックが必要です。

文字列や数値の場合には「th:value」を利用していましたが、チェックボックスの場合には値の取得および送信に「th:cheked」を利用します。

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>チェックボックスの送信</title>
</head>
<body>
  <form th:action="@{/checks}" method="POST" th:object="${formData}">  
    <p>
      <input id="checked" type="checkbox" name="select" th:checked="*{select}" />
      <label for="checked">選択チェックボックス</label>
    </p>
    <input type="submit" value="送信" />
  </form>
</body>
</html>

checkboxの場合には利用する属性が異なるということを覚えておきましょう。


5.よく使う属性一覧


これまで紹介した属性を含め、Thymeleafで利用する属性についてまとめて説明します。

属性名説明
th:value値の出力
th:if値の条件に合致する場合に子要素を表示
th:unless値の条件に合致しない場合に子要素を表示
th:objectモデル内のデータを読み込み、子要素内で参照できるようにする
th:fieldth:objectのフィールドを参照
th:valueinputのvalueに値を代入
th:checkedチェックボックスのチェック状態を操作
th:selectedセレクトボックスのoption要素の選択状態を操作
th:onclickクリック時のJavaScriptイベントを設定する
th:eachリストや配列でループして反復処理を行う
th:hrefaタグのhref要素に相当し、リンク式を用いてURLを設定
th:actionformタグのactionタグに相当し、リンク式を用いてフォームを送信するURLを指定




6.インライン形式でも処理が可能


これまでは、th:textのような属性を用いて値を表示する方法を紹介してきましたが、実はインライン形式でもThymeleafの処理を記述できます。

3. Spring BootでThymeleafを使ってみよう」で作成した「home.html」を以下のように変更してみましょう。

<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
  <h2>th:textを使った場合</h2>
    <div>
      <span th:text="${message}"></span>
  </div>
  <h2>インラインを使った場合</h2>
  <div>
    <span>[[${message}]]</span>
  </div>
</body>
</html>

実行すると、以下のようにどちらも同じメッセージを表示します。

ブラウザで「http://localhost:8080/home」にアクセスした画面

このように、属性値を使わなくてもインラインで変数を表示できます。
どちらも同じように動作するので、扱いやすい方法で記述するとよいでしょう。



※掲載された社名、製品名は、各社の商標及び登録商標です。


この記事をシェア