Thymeleafの標準式構文

「Thymeleaf」のth:xxxx=""の属性に何が書けるのかという構文の話。

執筆時バージョン
Java

Java SE 8

th:xxxx=""の属性には「単純式」「リテラル」「演算子」などを記述できる。

「単純式」はよく使うので4種類をしっかりおさえておきたい。「リテラル」「演算子」あたりは標準的ではあるが、HTMLに出力することが中心のため記号(&&など)よりも文字(and など)で書いた方がいい場合がある。

前提

コードのサンプルについてはSpring Bootを前提に作られていて、コントローラ側では次のような設定をしているモノとする。

String helloMessage = "こんにちは";
model.addAttribute("helloMessage", helloMessage);

Member member = new Member(1, "一郎");
model.addAttribute("member", member);

単純式

まずは単純式を把握する。次の4種類。記号がそれぞれ違う

変数式

${…​}

OGNLで指定された変数の値を表示する。

選択変数式

*{…​}

th:objectやth:fieldとセットで使う。指定した変数へのショットカートみたいなもの。

メッセージ式

#{…​}

メッセージプロパティと結びつけられた内容を表示する。

リンクURL式

@{…​}

リンクを生成する場合はこれ。コンテキストルートも考慮したパスを生成してくれる。

変数式

変数の値を表示する。OGNLなのでオブジェクトもgetterがあれば.(ドット)でたどれる。値がnullの場合は何も出力されない。

<section>
  <h3>変数式</h3>
  <p th:text="${helloMessage}"></p>
  <p>
    こんにちは、<span th:text="${member.name}"></span>さん
  </p>
  <p>
    nullの場合はこのように何も出力されない。「<th:block th:text="${null}"></th:block>」
  </p>
</section>
出力
<section>
  <h3>変数式</h3>
  <p>こんにちは</p>
  <p>
    こんにちは、<span>一郎</span>さん
  </p>
  <p>
    nullの場合はこのように何も出力されない。「」
  </p>
</section>

選択変数式

Springであればth:objectやth:fieldとセットで使う。指定した変数へのショットカートみたいなもの。

<section>
  <h3>選択変数式</h3>
  <p th:object="${member}">
    こんにちは、<span th:text="*{name}"></span>さん
  </p>
</section>
出力
<section>
  <h3>選択変数式</h3>
  <p>
    こんにちは、<span>一郎</span>さん
  </p>
</section>

リンクURL式

リンクを生成する場合は必ず使うようにする。次の点で有利。

  • コンテキストルートを考慮したパスを生成する

  • パスに変数値が含まれていても作成しやすい

<section>
  <h3>リンクURL式</h3>
  <a th:href="@{/members/{memberId}(memberId=${member.id})}" th:text="${member.name} + 'さんへのリンク'"></a>
</section>
出力
<section>
  <h3>リンクURL式</h3>
  <a href="/members/1">一郎さんへのリンク</a>
</section>

リテラル

属性値に""(ダブルクォート)は利用されているので、文字列は''(シングルクォート)になる。

シングルクォートも要らないリテラルトークンというものがあるが、文字(A-Z and a-z)、数字(0-9)、括弧([ と ]), ドット (.), ハイフン (-) アンダースコア (_)だけ。日本語はダメ。

<section>
  <h3>リテラル</h3>
  <ul>
    <li>テキストリテラル
      <ul>
        <li>th:text="'文字列です'" → <th:block th:text="'文字列です'" /></li>
      </ul>
    </li>
    <li>数値リテラル
      <ul>
        <li>th:text="0" → <th:block th:text="0" /></li>
        <li>th:text="34" → <th:block th:text="34" /></li>
        <li>th:text="3.0" → <th:block th:text="3.0" /></li>
      </ul>
    </li>
    <li>真偽値リテラル
      <ul>
        <li>th:text="true" → <th:block th:text="true" /></li>
        <li>th:text="false" → <th:block th:text="false" /></li>
      </ul>
    </li>
    <li>Nullリテラル
      <ul>
        <li>th:text="null" → <th:block th:text="null" /></li>
      </ul>
    </li>
    <li>リテラルトークン
      <ul>
        <li>th:text="abc" → <th:block th:text="abc" /></li>
      </ul>
    </li>
  </ul>
</section>
出力
<section>
  <h3>リテラル</h3>
  <ul>
    <li>テキストリテラル
      <ul>
        <li>th:text="'文字列です'" → 文字列です</li>
      </ul>
    </li>
    <li>数値リテラル
      <ul>
        <li>th:text="0" → 0</li>
        <li>th:text="34" → 34</li>
        <li>th:text="3.0" → 3.0</li>
      </ul>
    </li>
    <li>真偽値リテラル
      <ul>
        <li>th:text="true" → true</li>
        <li>th:text="false" → false</li>
      </ul>
    </li>
    <li>Nullリテラル
      <ul>
        <li>th:text="null" → </li>
      </ul>
    </li>
    <li>リテラルトークン
      <ul>
        <li>th:text="abc" → abc</li>
      </ul>
    </li>
  </ul>
</section>

演算子

論理演算では、HTMLに出力することが中心のため記号よりも文字で定義されている。

<section>
  <h3>演算子</h3>
  <ul>
    <li>テキスト演算子
      <ul>
        <li>th:text="'abc' + 'です。'" → <th:block th:text="'abc' + 'です。'" /></li>
      </ul>
    </li>
    <li>バイナリ演算子
      <ul>
        <li>th:text="1 - 2 * 3 / 4" → <th:block th:text="1 - 2 * 3 / 4" /></li>
        <li>th:text="3 % 2" → <th:block th:text="3 % 2" /></li>
      </ul>
    </li>
    <li>マイナス符号
      <ul>
        <li>th:text="-5" → <th:block th:text="-5" /></li>
      </ul>
    </li>
    <li>論理演算
      <ul>
        <li>th:text="true and true" → <th:block th:text="true and true" /></li>
        <li>th:text="true and false" → <th:block th:text="true and false" /></li>
        <li>th:text="true or false" → <th:block th:text="true or false" /></li>
      </ul>
    </li>
    <li>比較演算
      <ul>
        <li>th:text="1 > 0" → <th:block th:text="1 > 0" /></li>
        <li>th:text="1 >= 0" → <th:block th:text="1 >= 0" /></li>
        <li>th:text="1 gt 0" → <th:block th:text="1 gt 0" />(>)</li>
        <li>th:text="1 ge 0" → <th:block th:text="1 ge 0" />(>=)</li>
        <li>th:text="1 lt 0" → <th:block th:text="1 lt 0" />(&lt;)</li>
        <li>th:text="1 le 0" → <th:block th:text="1 le 0" />(&lt;=)</li>
      </ul>
    </li>
    <li>等価演算
      <ul>
        <li>th:text="1 == 1" → <th:block th:text="1 == 1" /></li>
        <li>th:text="1 eq 1" → <th:block th:text="1 eq 1" /></li>
        <li>th:text="1 != 1" → <th:block th:text="1 != 1" /></li>
        <li>th:text="1 ne 1" → <th:block th:text="1 ne 1" /></li>
      </ul>
    </li>
    <li>条件演算
      <ul>
        <li>th:text="true ? 'trueです'" → <th:block th:text="true ? 'trueです'" /></li>
        <li>th:text="true ? 'trueです' : 'falseです'" → <th:block th:text="true ? 'trueです' : 'falseです'" /></li>
        <li>th:text="false ? 'trueです' : 'falseです'" → <th:block th:text="false ? 'trueです' : 'falseです'" /></li>
        <li>th:text="null ?: 'デフォルトです'" → <th:block th:text="null ?: 'デフォルトです'" /></li>
      </ul>
    </li>
  </ul>
</section>
出力
<section>
	<h3>演算子</h3>
	<ul>
		<li>テキスト演算子
			<ul>
				<li>th:text="'abc' + 'です。'" → abcです。</li>
			</ul>
		</li>

		<li>バイナリ演算子
			<ul>
				<li>th:text="1 - 2 * 3 / 4" → -0.5</li>
				<li>th:text="3 % 2" → 1</li>
			</ul>
		</li>
		<li>マイナス符号
			<ul>
				<li>th:text="-5" → -5</li>
			</ul>
		</li>
		<li>論理演算
			<ul>
				<li>th:text="true and true" → true</li>
				<li>th:text="true and false" → false</li>
				<li>th:text="true or false" → true</li>
			</ul>
		</li>
		<li>比較演算
			<ul>
				<li>th:text="1 > 0" → true</li>
				<li>th:text="1 >= 0" → true</li>
				<li>th:text="1 gt 0" → true(>)</li>
				<li>th:text="1 ge 0" → true(>=)</li>
				<li>th:text="1 lt 0" → false(&lt;)</li>
				<li>th:text="1 le 0" → false(&lt;=)</li>
			</ul>
		</li>
		<li>等価演算
			<ul>
				<li>th:text="1 == 1" → true</li>
				<li>th:text="1 eq 1" → true</li>
				<li>th:text="1 != 1" → false</li>
				<li>th:text="1 ne 1" → false</li>
			</ul>
		</li>
		<li>条件演算
			<ul>
				<li>th:text="true ? 'trueです'" → trueです</li>
				<li>th:text="true ? 'trueです' : 'falseです'" → trueです</li>
				<li>th:text="false ? 'trueです' : 'falseです'" → falseです</li>
				<li>th:text="null ?: 'デフォルトです'" → デフォルトです</li>
			</ul>
		</li>
	</ul>
</section>

Appendix B: 改訂履歴

  • v1.0, 2017-05-03: 初稿