Spring Boot解説第17回(開発環境編：Thymeleafその3 ~Thymeleafの属性と構文~)

こんにちはこんばんは！
株式会社情創 技術開発局
先日焼き肉を食べに行って大満足の@YAKINIKUです。

今回で開発環境編は終わりです。
次回からは基本編に入ります。
今回はThymeleafの属性と構文およびjsp、jstlタグとの比較について解説していきます。

# Thymeleaf 属性
[第15回](http://qiita.com/YAKINIKU/items/44cdbebbe9788992386b "Spring Boot解説第15回(開発環境編：Thymeleafその１) - Qiita")でも少し説明しましたが、Thymeleaf では独自の属性を提供しています。
その中でも主要なものについて解説します。

## th:text、th:utext
この属性に設定した値を、タグ内のテキストに設定します。
後述する変数式の構文 ${...} と合わせて使われることが多いです。

```html:template
<p th:text="${text}">test</p>
<p th:utext="${text}">test</p>
```

上記の例では、変数 text の値を test の部分に置き換えます。
th:text は自動でエスケープを行いますが、th:utext はエスケープを行いません。
必要に応じて使い分けましょう。

## th:href
リンク先のURLを設定します。
後述するリンクURL式の構文 @{...} と合わせて使われることが多いです。
この属性の使い方には以下のようなものがあります。

### クエリ形式
クエリのパラメータを設定するには、クエリ形式で記述します。
URLの後ろに(パラメータ名=値)の形で設定します。
複数のパラメータを設定する場合はカンマ「,」で区切ります。

```html:template
<a href="/test" th:href="@{/test(id=${id},name=${name})}">test page</a>
```

### REST形式
URLの一部に値を設定する場合はREST形式で記述します。
REST形式ではプレースホルダをURLの文字列中に{プレースホルダ名}で定義し、URLの後ろに(プレースホルダ名=値)で表示する内容を設定します。

```html:template
<a href="/test" th:href="@{/test/{id}/{seq}(id=${id},seq=${seq})}">test page</a>
```

## th:each
この属性に設定した変数(コレクション)のサイズだけ、タグの内部を繰り返します。
List の各要素にアクセスする場合などに使用され、記述を簡潔にしてくれます。

```html:template
<tbody th:each="list : ${beans}">
    <tr>
        <td class="text-str" th:text="${list.id}"></td>
        <td class="text-str" th:text="${list.name}"></td>
    </tr>
</tbody>
```

上記の例では、beans の各要素を list とし、メンバー変数の id と name を表示しています。

## th:object
選択するオブジェクトを設定します。
設定されたオブジェクトは、後述する選択変数式の構文 *{...} を使用することで、このタグ内での記述を省略できます。

```html:template
<tbody th:each="list : ${beans}" th:object="${list}">
    <tr>
        <td class="text-str" th:text="*{id}"></td>
        <td class="text-str" th:text="*{name}"></td>
    </tr>
</tbody>
```

## th:if、th:unless
th:if は設定された条件式が真の場合のみ、タグを有効にします。
条件式が偽の場合はタグそのものが無視されます。

```html:template
<p th:if="${errorMsg} != null">エラーメッセージ</p>
```

上記の例では、変数 errorMsg が null 以外のときに「エラーメッセージ」を出力します。

if の次は else になりそうですが、Thymeleaf では else ではなく unless になります。
th:unless は設定された条件式が偽の場合のみ、タグを有効にします。

```html:template
<p th:unless="${errorMsg} == ''">エラーメッセージ</p>
```

上記の例では、変数 errorMsg が空でないときに「エラーメッセージ」を出力します。

## th:switch、th:case
Thymeleaf では switch 文も使用できます。
th:switch を設定したタグの内部に、th:case を設定したタグを記述します。
なお、break は必要なく、th:case に設定した値と一致したタグのみ有効になります。
どの値とも一致しない場合は "*" の値を設定したタグが有効になります。

```html:template
<td th:switch="${num}">
    <p th:case="0">ZERO</p>
    <p th:case="1">ONE</p>
    <p th:case="*">NUM</p>
</td>
```

## その他の属性
この他にも使用できる属性はありますが、数が多いので割愛させていただきます。
以下のページを参照してください。

[Tutorial: Using Thymeleaf (ja)](http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html "Tutorial: Using Thymeleaf (ja)")

# Thymeleaf 構文
Thymeleaf は属性と同様に、多くの構文も提供しています。

## 変数式 ${...}
変数を設定することで、その変数を参照します。
この記述は、実際には OGNL(Object-Graph Navigation Language) 式と呼ばれ、変数マップ上で実行されます。
OGNL 式については[こちら](http://commons.apache.org/proper/commons-ognl/ "OGNL - Apache Commons OGNL - Object Graph Navigation Library")を参照してください。

```html:template
<p th:text="${text}">test</p>
```

## 選択変数式 *{...}
前述した th:object で指定したオブジェクトに対して参照します。
同じオブジェクトのメンバを参照する場合に、記述を省略できるので便利です。

```html:template
<tbody th:each="list : ${beans}" th:object="${list}">
    <tr>
        <td class="text-str" th:text="*{id}"></td>
        <td class="text-str" th:text="*{name}"></td>
    </tr>
</tbody>
```

上記の出力は、以下の記述の出力と同じになります。

```html:template
<tbody th:each="list : ${beans}">
    <tr>
        <td class="text-str" th:text="${list.id}"></td>
        <td class="text-str" th:text="${list.name}"></td>
    </tr>
</tbody>
```

## メッセージ式 #{...}
あらかじめ用意していたメッセージをそのまま表示する際に使用します。
メッセージはjava プログラムではなく、リソースファイルに記述されることが多いですが、これを用いることでプログラムを介することなく、テンプレートから直接メッセージを扱えます。

```properties:message
hello.msg=Hello World
```

```html:template
<p th:text="#{hello.msg}"></p>
```

## リンクURL式 @{...}
URLを設定する際に使用します。
th:href の項目でも触れましたが、変数を使ってURLを生成する場合は、この構文を使うことになります。

```html:template
<a href="/test" th:href="@{/test(id=${id},name=${name})}">test page</a>
```

## リテラルの記述
Thymeleaf におけるリテラルの記述において主要なものを説明します。

### 文字列
文字列はシングルクォート「'」で囲みます。
なお、シングルクォート自体を記述する場合は、「\'」としてエスケープする必要があります。

```html:template
<p th:text="'text'">test</p>
<p th:text="'single quote\''">test</p>
```

### 数値
数値は特別な記述は必要なく、そのまま記述します。

```html:template
<p th:text="123">test</p>
```

### 真偽値
true もしくは false を記述します。

```html:template
<p th:if="${flag} == true">test</p>
```

### Null
null を記述します。

```html:template
<p th:if="${errorMsg｝ != null">エラーメッセージ</p>
```

## オブジェクト
Themeleaf は記述を簡潔にする手助けをしてくれるオブジェクトを提供しています。
これらは共通して # から始まります。
種類が多いので、説明は割愛します。
種類は以下のページを参照してください。

[Tutorial: Using Thymeleaf (ja)#式の基本オブジェクト](http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html#式の基本オブジェクト "Tutorial: Using Thymeleaf (ja)#式の基本オブジェクト")

## その他の構文
その他の構文については、以下のページを参照してください。

[Tutorial: Using Thymeleaf (ja)#スタンダード式構文](http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html#スタンダード式構文 "Tutorial: Using Thymeleaf (ja)#スタンダード式構文")

# jsp、jstl タグとの比較
以上のように、Thymeleaf を使えば通常のhtmlファイルに対して java プログラムの変数値を使用することができたり、ループや条件分岐などのプログラム的要素を簡潔に記述することができます。
今までは jspや、jsp の標準タグライブラリである jstl がこの役割を担っていました。

そこで、jsp、jstl での記述が Thymeleaf ではどのように置き換えることができるのかを説明していきます。

## 日付表示
日付の表示には java.util.Date (以下 Date と省略)オブジェクトや java.util.Calendar (以下 Calendar と省略)オブジェクトが使われます。
jstl では以下のように記述します。

```jsp:jstl
<p><fmt:formatDate value="${date}" pattern="yyyyMMdd" /></p>
```

Thymeleaf ではオブジェクトや th:text 属性を使って以下のように記述します。

```html:Thymeleaf
<p th:text="${#dates.format(date,'yyyyMMdd')}"></p>
```

\#dates は Thymeleaf が提供するユーティリティオブジェクトの一つで、Date オブジェクトに対するメソッド群です。
変数 date には Date オブジェクトを指定します。

他にも Calendar オブジェクトに対するメソッド群である #calendars を使用すれば、Date オブジェクトと同様に日付表示が行えます。

## 複数条件分岐

jstl では以下のように記述します。

```jsp:jstl
<td>
　　<c:choose>
　　　　<c:when test="${num == 0}"><p>ZERO</p></c:when>
　　　　<c:when test="${num == 1}"><p>ONE</p></c:when>
　　　　<c:otherwise><p>NUM</p></c:otherwise>
　　</c:choose>
</td>
```

分岐を行う部分を`<c:choose>`で囲み、`<c:when test="条件文">`で判定をします。
「それ以外」の分岐は`<c:otherwise>`で記述します。

対して、Thymeleaf では th:switch の項目で説明したように、以下のような記述をします。

```html:Thymeleaf
<td th:switch="${num}">
    <p th:case="0">ZERO</p>
    <p th:case="1">ONE</p>
    <p th:case="*">NUM</p>
</td>
```

## 比較結果
以上の比較からは、どちらが良いか一概には言えませんが、タグではなく属性で記述できる Thymeleaf のほうが記述量が少なくて済みます。

また、Thymeleaf はそのまま html ファイルとしてブラウザに表示できることが大きな利点です。
jsp および jstl ではデータを渡すサーブレット側の実装を待たなければ表示の確認ができません。
それに対してThymeleaf では変数表示部分の記述は無視されるので、すぐに表示の確認ができます。

その他の対応については以下のページを参照してください。
[Tutorial: Using Thymeleaf (ja)](http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html "Tutorial: Using Thymeleaf (ja)")
[ＪＳＴＬリファレンス](http://struts.wasureppoi.com/jstl/00_jstl.html "ＪＳＴＬリファレンス")

では今回はこの辺で終わりにします。
最後まで読んでいただきありがとうございました。
それではみなさんまた会いましょう！

# 参考URL
[Thymeleafの機能メモ - Qiita](http://qiita.com/rubytomato@github/items/ac65c2203d16d1a1bbd7 "Thymeleafの機能メモ - Qiita")