Thymeleaf 構文一覧
- 解説
- 1. はじめに
- 2. 基本構文
- 3. ユーティリティメソッド
解説
1. はじめに
このページは、Thymeleafでよく使用される構文・ユーティリティメソッドをまとめたチートシートです。重要度の高い構文は目次下のタグに表示されており、クリックすることで該当の構文にスクロールします。
以下、チートシートの見方です。
サーバー実行前のThymeleaf構文を含むHTMLの例
結果
上のHTMLファイルをサーバー実行した後のHTML
2. 基本構文
${…} (値の取得)
「${}」で変数を囲うことで値を取得することが可能です。
<p th:text="${id}"></p>
結果
<p>1</p>
'' + ${…} (値の結合)
「+」で値や文字列を結合することが可能です。
<p th:text="'Hello ' + ${name}"></p>
結果
<p>Hello DigSkill</p>
th:with (ローカル変数の定義)
「th:with="変数名=値"」 で変数を定義して値を代入することが可能です。ただし、利用可能なのは定義したタグの中だけです。
<div th:with="name='DigSkill'">
<p th:text="${name}"></p>
</div>
結果
<div>
<p>DigSkill</p>
</div>
th:utext (非エスケープ)
「th:utext」を使用することで、HTMLタグをエスケープせずに表示することが可能です。
<p th:text="'Hello<br>' + ${user.name}"></p>
<p th:utext="'Hello<br>' + ${user.name}"></p>
結果(画面出力)
Hello<br>DigSkill
Hello
DigSkill
${param} (リクエストパラメータの取得)
「/index?id=1」のようなリクエストパラメータを取得したい場合、「param」という特別な変数を使用して「param.id」のように指定して取得することが可能です。
<p th:text="${param.id}"></p>
結果
<p>1</p>
${object.id} (フィールドの取得)
オブジェクトの後に、「.(ピリオド)」続きでフィールド名を指定することでフィールドを取得することが可能です。ただし、getterを定義しておく必要があります。
<!-- 以下の場合 getId() というgetterを定義しておく -->
<p th:text="${user.id}"></p>
結果
<p>1</p>
th:object (フィールドの取得)
「th:object="${…}"」のように、オブジェクトを指定したタグの中でのみ「*{…}」の形でフィールドを取得することが可能です。
<div th:object="${user}">
<p th:text="*{id}"></p><!-- ${user.id} と同じ -->
</div>
結果
<div>
<p>1</p>
<dib>
+, -, *, /, % (算術演算子)
「+」「-」「*」「/」「%」が使用可能です。
<p th:text="3 + 2"></p>
<p th:text="3 - 2"></p>
<p th:text="3 * 2"></p>
<p th:text="3 / 2"></p>
<p th:text="3 % 2"></p>
結果
<p>5</p>
<p>1</p>
<p>6</p>
<p>1.5</p>
<p>1</p>
>, <, >=, <= (比較演算子)
「>」「<」「>=」「<=」が使用可能です。 ただし、「>」と「<」は使用すべきではないので、代わりに「gt」と「lt」を使用します。また、以下の文字列エイリアスも使用可能です。
「ge(>=)」「le(<=)」
<p th:text="3 gt 2"></p>
<p th:text="3 lt 2"></p>
<p th:text="3 ge 2"></p>
<p th:text="3 le 2"></p>
結果
<p>true</p>
<p>false</p>
<p>true</p>
<p>false</p>
==, != (等価演算子)
「==」と「!=」が使用可能です。また、以下の文字列エイリアスも使用可能です。
「eq(==)」「neqまたはne(!=)」
<p th:text="3 eq 3"></p>
<p th:text="'DigSkill' ne 'DigSkill'"></p>
結果
<p>true</p>
<p>false</p>
x?y:z (条件式)
三項演算子のように、条件を評価した結果により処理を分けることが可能です。
<p th:text="${user.isAdmin} ? '管理者ユーザー' : '一般ユーザー'"></p>
結果
<!-- user.isAdmin が true の場合 -->
<p>管理者ユーザー</p>
x?:y (デフォルト式)
「?:(エルビス演算子)」を使用することで、左辺の式の結果がnull以外の場合にはその値を、 nullの場合には右辺の値を取得します。
<p th:text="${user.name} ?: '名無し'"></p>
<!-- 以下の内容と同じ -->
<p th:text="${user.name != null} ? ${user.name} : '名無し'"></p>
結果
<p>DigSkill</p>
_ (処理なしトークン)
Thymeleaf ではタグ間の文字列より、th:textの値が優先されます。しかし、「_(アンダースコア)」を使用することで「th:text」による処理を無かったことにでき、タグ間の文字列をデフォルト値にように使用することが可能です。
<p th:text="${user.name} ?: _">名無し</p>
結果
<p>名無し</p>
|${…}| (リテラル置換)
文字列や変数を「|(縦棒)」で囲うことで、「+」を使わず変数を埋め込んだ文字列を作成することが可能です。リテラル置換内では、文字列を「’(シングルクォート)」で囲う必要はありません。
<p th:text="|Hello ${user.name}|"></p>
結果
<p>Hello DigSkill</p>
th:if (条件分岐)
「th:if="条件"」を使用すると、条件がtrueの場合にのみこのタグと中身を表示することが可能です。また、真偽値のtrue以外にも以下の値がtrueと評価されます。
0以外の数値 |
false, off, no以外の文字列 |
真偽値でも、数値でも、文字列でも、nullでもない場合 |
<!-- user.isAdmin = true の場合 -->
<div th:if="user.isAdmin">
<p>管理者ユーザー</p>
</div>
結果
<div>
<p>管理者ユーザー</p>
</div>
th:unless (条件分岐)
「th:unless="条件"」を使用すると、条件がfalseの場合にのみこのタグと中身を表示することが可能です。また、真偽値のfalse以外にも以下の値がfalseと評価されます。
数値の 0 |
文字列の false, off, no |
null値 |
<!-- user.isAdmin = false の場合 -->
<div th:unless="user.isAdmin">
<p>一般ユーザー</p>
</div>
結果
<p>一般ユーザー</p>
th:switch / th:case (多項分岐)
「th:switch」と「th:case」をセットで使用することでJavaのswitch文のように条件ごとに表示を変更することが可能です。どの条件にも一致しない場合に表示されるデフォルトとして、「th:case="*"」が使用可能です。
<div th:switch="${user.authLevel}">
<p th:case="1">マスターユーザー</p>
<p th:case="2">管理者ユーザー</p>
<p th:case="3">一般ユーザー</p>
<p th:case="*">未ログイン</p>
</div>
結果
<!-- user.authLevel = 1 の場合 -->
<div>
<p>マスターユーザー</p>
</div>
th:each (ループ)
「th:each="変数 : 繰り返し可能なオブジェクト"」を使用することで、オブジェクトから値を一つずつ変数に代入し、ループ処理をすることが可能です。
<div th:each="page : ${pages}">
<p th:text="${page}"></p>
</div>
結果
<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
<p>Java</p>
<p>PHP</p>
<p>Python</p>
</div>
stat (ステータス変数)
ステータス変数を使用することで「th:each」の中で繰り替えし処理のステータスを取得することが可能です。ステータス変数は「th:each」内で、繰り返し用変数の後にカンマ区切りで名前を指定でき、明示的に指定しない場合は、繰り返し用変数の後ろにStatをつけた変数名で作成されます。ステータス変数は以下のデータを保持しています。
index | 0から始まる現在のインデックス |
count | 1から始まる現在のインデックス |
size | 全要素数 |
current | 現在の要素オブジェクト |
even | 現在の繰り返し処理が偶数かどうか |
odd | 現在の繰り返し処理が奇数かどうか |
first | 現在の繰り返し処理が最初かどうか |
last | 現在の繰り返し処理が最後かどうか |
<div th:each="page, stat : ${pages}">
<p th:text="stat.count"></p>
<p th:text="page"></p>
</div>
結果
<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
<p>1</p>
<p>Java</p>
<p>2</p>
<p>PHP</p>
<p>3</p>
<p>Python</p>
</div>
__${…}__ (プリプロセッシング)
Thymeleaf ではネストした式を作成する場合、先に中の式を評価する必要があります。その場合「_(アンダースコア)」2つで囲うことで、先に評価することが可能です。
<div th:each="page, stat : ${pages}">
<p th:text="${pages[__${stat.index}__]}"></p>
</div>
結果
<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
<p>Java</p>
<p>PHP</p>
<p>Python</p>
</div>
[[…]] (インライン化)
「[](角括弧)」2つで囲うことで、HTMLタグ外に直接式を記述することが可能です。また、「[()]」で囲うことでHTMLタグをエスケープせずに出力します。(th:utextと同義)
<div th:with="name='Hello<br>' + ${user.name}">
<p>[[${name}]]</p>
<p>[(${name})]</p>
</div>
結果(画面出力)
Hello<br>DigSkill
Hello
DigSkill
/*[[${…}]]*/ (JavaScriptのインライン化)
scriptタグに「th:inline="javascript"」を指定することで、scriptタグ内でもThymeleaf式を使用することが可能です。ただし、HTML単体で表示するとエラーが発生するので、コメント化することによりサーバーで実行された場合とHTML単体で表示された場合で処理を分けることが可能です。
<script th:inline="javascript">
const name = [[${user.name}]];
</script>
<!-- HTML単体で表示される可能性がある場合 -->
<script th:inline="javascript">
const name = /*[[${user.name}]]*/ 'HTML単体で表示された場合の値';
</script>
#{…} (メッセージを取得する)
「#{...} (メッセージ式)」を使用することで「src > resources」直下に作成した「messages.properties」ファイル内に定義したメッセージを取得することが可能です。
greeding.morning = おはようございます!
<p th:text="#{greeding.morning}"></p>
結果
<p>おはようございます!</p>
@{…} (リンクを作成する)
「@{…}(リンクURL式)」を使用することで、動的にURLを作成することが可能です。「/」から始まる相対URLを指定した場合は、自動でURL先頭にコンテキストパスが追加されます。
また、「()(丸括弧)」内で値を指定することで、パス・リクエストパラメーターを動的に定義することも可能で、パスを動的に変更する場合は「{}(波括弧)」で囲います。
<a th:href="@{/home/{action}(id=${user.id}, content='Hello', action=${action})}">送信</a>
結果
<a href="/greeting_app/home/create?id=1&content=Hello">送信</a>
th:block (擬似ブロック)
「th:block」要素はth属性実行後に削除されるため、th属性を指定するためだけの余分なタグを作成せずにすみます。
<th:block th:if="${user.isAdmin}">
<p>管理者</p>
</th:block>
結果
<p>管理者</p>
th:insert (フラグメントの挿入)
「th:insert="ファイル名::th:fragmentで指定した値"」を使用することで指定したフラグメントを「th:insert」を指定したタグ直下に挿入することが可能です。
<footer th:fragment="copyright">
© 2022 Dig Skill
</footer>
<div th:insert="footer::copyright"></div>
結果
<div>
<footer>© 2022 Dig Skill</footer>
</div>
th:replace (フラグメントで置換)
「th:replace="ファイル名::th:fragmentで指定した値"」を使用することで指定したフラグメントで「th:replace」を指定したタグを置き換えることが可能です。
<footer th:fragment="copyright">
© 2022 Dig Skill
</footer>
<div th:replace="footer::copyright"></div>
結果
<footer>© 2022 Dig Skill</footer>
3. ユーティリティメソッド
${#dates.format(…)} (標準ロケールフォーマットで日付をフォーマット)
<p th:text="${#dates.format(today)}"></p>
結果
<p>2022年1月1日 00:00:00 JST</p>
${#dates.formatISO(…)} (ISO8601フォーマットで日付をフォーマット)
<p th:text="${#dates.formatISO(today)}"></p>
結果
<p>2022-01-01T00:00:00.000+09:00</p>
${#dates.format(…, パターン)} (指定したパターンで日付をフォーマット)
<p th:text="${#dates.format(today, 'YYYY-MM-dd HH:mm')}"></p>
結果
<p>2022-01-01 00:00</p>
${#dates.year(…)} (日付のプロパティを取得)
<p th:text="${#dates.year(today)}"></p>
<p th:text="${#dates.month(today)}"></p>
<p th:text="${#dates.day(today)}"></p>
<p th:text="${#dates.dayOfWeekName(today)}"></p>
<p th:text="${#dates.hour(today)}"></p>
<p th:text="${#dates.minute(today)}"></p>
<p th:text="${#dates.second(today)}"></p>
<p th:text="${#dates.millisecond(today)}"></p>
結果
<!-- 2022/01/31 12:34:56:789 の場合 -->
<p>2022</p><!-- 年 -->
<p>1</p><!-- 月 -->
<p>31</p><!-- 日 -->
<p>月曜日</p><!-- 曜日 -->
<p>12</p><!-- 時 -->
<p>34</p><!-- 分 -->
<p>56</p><!-- 秒 -->
<p>789</p><!-- ミリ秒 -->
${#dates.createNow()} (現在日時のDateオブジェクトを作成)
<p th:text="${#dates.createNow()}"></p>
結果
<p>Mon Jan 31 12:34:56 JST 2022</p>
${#numbers.formatInteger(…, 桁数)} (整数の最小桁数を指定)
<p th:text="${#numbers.formatInteger(num,3)}"></p>
結果
<!-- num = 11 の場合 -->
<p>011</p><!-- 指定した桁数になるよう0埋めされる -->
${#numbers.sequence(x, y)} (xからyまでの整数の配列を作成)
<div th:with="nums = ${#numbers.sequence(1, 3)}">
<div th:each="num : ${nums}">
<p th:text="${num}"></p>
</div>
</div>
結果
<div>
<div>
<p>1</p>
<p>2</p>
<p>3</p>
</div>
</div>
${#strings.isEmpty(…)} (文字列が空(もしくはnull)かどうかをチェック)
<div th:with="name=''">
<p th:text="${#strings.isEmpty(name)}"></p>
</div>
結果
<div>
<p>true</p>
</div>
${#strings.defaultString(…, 'デフォルト')} (文字列が空もしくはnullの場合デフォルト文字列を返却)
<div th:with="name=''">
<p th:text="${#strings.defaultString(name, '名無し')}"></p>
</div>
結果
<div>
<p>名無し</p>
</div>
${#strings.contains(…, '文字列')} (指定した文字列が含まれているかどうかをチェック)
<div th:with="name='DigSkill'">
<p th:text="${#strings.contains(name, 'Dog')}"></p>
</div>
結果
<div>
<p>false</p>
</div>
${#strings.startsWith(…, '文字列')} (指定した文字列で始まっているかどうかをチェック)
<div th:with="name='DigSkill'">
<p th:text="${#strings.startsWith(name, 'Dig')}"></p>
</div>
結果
<div>
<p>true</p>
</div>
${#strings.endsWith(…, '文字列')} (指定した文字列で終わっているかどうかをチェック)
<div th:with="name='DigSkill'">
<p th:text="${#strings.endsWith(name, 'Skill')}"></p>
</div>
結果
<div>
<p>true</p>
</div>
${#strings.indexOf(…, '文字列')} (指定した文字列が最初に出現する位置を取得)
<div th:with="name='DigSkill'">
<p th:text="${#strings.indexOf(name, 'S')}"></p>
</div>
結果
<div>
<p>3</p><!-- 0 始まりなので 4文字目 -->
</div>
${#strings.substring(…, x, y)} (指定した位置の文字列を切り出す)
<div th:with="name='DigSkill'">
<p th:text="${#strings.substring(name, 3, 8)}"></p>
</div>
結果
<div>
<p>Skill</p>
</div>
${#strings.replace(…, …, …)} (指定した文字列で置き換え)
<div th:with="name='DigSkill'">
<p th:text="${#strings.replace(name, 'S', ' S')}"></p>
</div>
結果
<div>
<p>Dig Skill</p>
</div>
${#strings.arrayJoin(…, '')} (配列を指定文字列区切りで結合)
<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#strings.arrayJoin(names, '')}"></p>
結果
<p>オンラインプログラミング学習サービスDigSkill</p>
${#arrays.length(…)} (配列の要素数を取得)
<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#arrays.length(names)}"></p>
結果
<p>5</p>
${#arrays.contains(…, …)} (要素が配列に含まれているかどうかをチェック)
<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#arrays.contains(names, 'プログラミング')}"></p>
結果
<p>true</p>
${#aggregates.sum(…)} (配列、コレクションの合計値を取得)
<!-- int[] nums = {1, 2, 3, 4, 5}; -->
<p th:text="${#aggregates.sum(nums)}"></p>
結果
<p>15</p>
${#aggregates.avg(…)} (配列、コレクションの平均値を取得)
<!-- int[] nums = {1, 2, 3, 4, 5}; -->
<p th:text="${#aggregates.avg(nums)}"></p>
結果
<p>3</p>