このシリーズの(1)、(2)で紹介したように、Spring Boot Web アプリの雛形プロジェクトを作成した後は、Spring MVC で開発する場合とあまり変わりません。Spring の基本設定もデフォルト状態で使う場合、Spring Boot がやってくれるので簡単です。今回はSpring Boot + Thymeleaf でよく使う機能をおさらいしてみました。
Artifact id = bootThyme
Name = bootThyme
最終的なプロジェクトの構造は以下のようになります:
大部分のソースは SpBootDemo と変わりませんが、異なる部分を以下に掲載します。
上の home.html で Thymeleafを使っている部分を順に見ていきます。
home ビューの画面は次のようになります。
sample01 ビューを表示して上記の結果を確認します:
・リンクURL式 @{...} を使って画像ファイルを指定する
sample02 ビューの表示結果:
・リクエストパラメータを表示する
sample03 ビューの表示結果(2):
・セッション属性を表示する
sample04 ビューの表示結果:
・変数式 ${...}、繰り返し(th:eachと繰り返し変数)、条件判定
sample05.html ビューの表示結果:
・選択変数式 *{...} の使い方
sample06 ビューを表示します:
・変数式 ${...} を javascript の変数に代入する
sample07 ビューを表示します:
ソースコード:GitHub の bootThymeからダウンロードできます。
- テンプレートフラグメントのインクルード
- Thymeleaf の日付、数値ユーティリティの使い方
- リンクURL式 @{...} を使って画像ファイルを指定する
- リクエストパラメータを表示する
- セッション属性を表示する
- 変数式 ${...}、繰り返し(th:eachと繰り返し変数)、条件判定
- 選択変数式 *{...} の使い方
- 変数式 ${...} を javascript の変数に代入する
プロジェクトの作成
「(1)Spring Boot で Web アプリケーションを開発:プロジェクトの作成」と同じように、新規プロジェクト(プロジェクト名は bootThyme) を作成します。Artifact id = bootThyme
Name = bootThyme
最終的なプロジェクトの構造は以下のようになります:
![]() | ![]() |
モデルを追加
このサンプル・アプリで使用するモデルクラスを作成します。Tutorial: Using Thymeleaf (ja)で使用されているモデルと同じものを作成します。home.html の作成
サンプル・アプリ起動時に表示されるビュー src/main/resources/templates/views/home.html を作成します。上の home.html で Thymeleafを使っている部分を順に見ていきます。
- 4行: th:include="fragment/frag01 :: htmlhead"
これは複数のページで共通のコード断片(上の場合 src/main/resources/templates/views/fragment/frag01.html で定義した htmlhead フラグメント)をインクルードします。 - 5行: th:with="title=#{app.title}, navColorCss='navBarBlue01'"
共通部分の一部をパラメータで置き換えることができます。ここでは- titleパラメータでヘッダのタイトルに #{app.title} を設定します。さらに #{app.title} は messages.properties で app.title プロパティにセットされた文字列 "Spring Boot + Thymeleaf"に置き換えられます。
- navColorCssパラメータでナビゲーションバーのスタイルを設定する CSS ファイルを指定していします。
- 8-9行:th:include="fragment/frag01 :: navbar" th:with="title=#{app.title}"
4-5行と同じですが、ここではインクルードするフラグメントとして navbar(ナビゲーションバー)を指定します。title パラメータには5行と同じく #{app.title}を設定しています。 - 41-42行:"fragment/frag01 :: footer" th:with="title=#{app.footer}"
これも 4-5行と同じで、ページのフッター部分(footerフラグメント)をインクルードします。 - 16行:th:utext="#{home.welcome(${userName})}
この行では、home ページのウェルカムメッセージを表示しています。 <h3>タグや<span>タグなどでテキストを出力するには th:text, th:utext を使用します。ここでは、<h3>のテキストとして messages.properties の home.welcome プロパティの内容 "{0} さん、これは <b>Spring Boot Demo アプリケーション!</b> です。"を出力します。さらに、{0}の部分は Thymeleaf の変数式 ${userName} で置き換えられます。<b>によるボールド指定を有効にするには th:utext を使用する必要があります(th:text では自動的にエスケープされます)。${userName} の値は HomeController.home() の Model#addAttribute("userName", "ログインユーザー"); によりセットされた "ログインユーザー"です。 - 19行:th:text="${today}
addAttribute("today", Calendar.getInstance().getTime()); によりセットされたシステム日を表示します。 - 24-38行:home.html から Thymeleaf の使い方を示すサンプルページを呼び出します。
home ビューの画面は次のようになります。
Thymeleaf の使い方サンプル
・Thymeleaf の日付、数値ユーティリティの使い方- 10行:th:text="${#dates.format(today,'yyyy/MM/dd EE')}"
17行:th:text="${#dates.format(today,'yyyy/MMM/dd HH:mm')}"コントローラから送られたシステム日(today) に 書式'yyyy/MM/dd EE' ,'yyyy/MMM/dd HH:mm'を設定します。 - 23行:th:text="${#dates.createToday()}"
現在日のオブジェクトを作成します。 - 29行:th:text="${#dates.year(today)}"
渡された日付引数から日付プロパティを取得します。この例はでは"年"を取得します。 "月"や "日"を取得するには、#dates.month(..)、#dates.day(..) を使用します。 - 39行:th:text="${#numbers.formatDecimal(double1,5,3)}"
コントローラから送られた double 値に "00000.000"の書式を設定します。 1234.567 は 01234.567 で出力されます。ゼロパディングをしないようにするには(double1,1,3)のように指定します。コントローラから送られた値が int 値や String 値の場合でも同じように使用できます。
sample01 ビューを表示して上記の結果を確認します:
・リンクURL式 @{...} を使って画像ファイルを指定する
- 6行:th:src="@{./img/Red Apple.gif}"
7行:th:src="@{img/Sunflower.gif}"
前者は "src/main/resources/static/img/Red Apple.gif"を、後者は "src/main/resources/static/img/Sunflower.gif"を参照します。
その他の例: th:href="@{/css/app_base.css}"は、 "src/main/resources/static/css/app_base.css"を参照します。
sample02 ビューの表示結果:
・リクエストパラメータを表示する
- 21行:th:text="${param.size()}"
リクエストパラメータのサイズを表示します。このページは "@{sample03?param1=aaa}"で呼ばれるので、サイズは1となります。 - 22行:th:text="${param.isEmpty()}"
リクエストパラメータの有無を判定します。パラメータは有るので、false を表示します。 - 23行:th:text="${param.param1 + ''}"
パラメータ param1 の内容を表示します。 aaa が表示されます。
- 2-3行:th:unless="${param.param2}" th:include="fragment/frag01 :: htmlhead"
4行:th:with="title=#{app.title}"
5-6行:th:if="${param.param2}" th:include="fragment/frag01 :: htmlhead"
7行:th:with="title=#{app.title}, navColorCss='navBarRed01'"
あまり実用的な例ではありませんが、リクエストパラメータ param2 の有無を判定してナビゲーションの色を変えます。param2 が無ければ(th:unless="${param.param2}")、2-4行が有効になって、パラメータ navColorCss は設定されません。param2 が有れば(th:if="${param.param2}")、5-7行が有効になって、パラメータ navColorCss に 'navBarRed01'が設定されます。ブラウザのURL入力で、"localhost:9000/bootThyme/sample03?param1=aaa¶m2=1"を入力してください。赤いナビゲーションバーが表示されます。
sample03 ビューの表示結果(2):
・セッション属性を表示する
- 12行:th:text="${session.size()}"
HttpSession に登録されたオブジェクトのサイズを表示します。HttpController.sample4() ではsession.setAttribute("str1", "文字列");
で2つのオブジェクトを登録しているのでサイズは2になります。
session.setAttribute("cust2", new Customer(102, "顧客00002",
DateTime.now().minusMonths(20).toCalendar(Locale.JAPAN))); - 13行:th:text="${session.isEmpty()}"
セッション属性の有無を判定します。2つのオブジェクトが有るので falseが表示されます。 - 14行:th:text="${session.str1 + ''}"
"str1"の内容 "文字列"が表示されます。 - 15行:th:text="${session.cust2.name + ''}"
"cust2.name"の内容 "顧客00002"が表示されます。
sample04 ビューの表示結果:
・変数式 ${...}、繰り返し(th:eachと繰り返し変数)、条件判定
- 15行:th:each="prod : ${products}"
${products} はHomeController.sample05() でモデルに登録した List<Product> を参照します。th:each はリストの要素数だけ繰り返します。各要素は、繰り返し変数 prod で参照できます。<tr> タグに記述した場合、テーブル行が要素の数だけ出力されます。 - 16行:th:class="${prodStat.odd} ? 'odd'"
prodStat ステータス変数は Thymeleaf により自動的に作成され、繰り返しの状態を保持します(prodStat という名前は prod にStat が自動的に追加されたものです)。
ステータス変数は属性の中で定義され、以下の内容を保持しています:- index: 0始まりの現在の「繰り返しインデックス」
- count: 1始まりの現在の「繰り返しインデックス」
- size: 被繰り返し変数の全要素数
- current: 繰り返し中の「繰り返し変数」
- even/odd: 現在の繰り返し処理が偶数か奇数か
- first: 現在の繰り返し処理が最初かどうか
- last: 現在の繰り返し処理が最後かどうか
- 17行:th:text="${prod.id}"
対象行のID列に、リスト内の該当 Product インスタンスの id の値を表示します。 - 20行:th:text="${prod.inStock} ? 'o' : 'x'"
prod.inStock が true なら 'o'を false なら 'x'を表示します。 - 23-24行:th:if="${prod.inStock}==true" th:id="${prod.id}" onclick="alert(this.id)"
th:if で ${prod.inStock} の true | false を判定しています。20行のように ${prod.inStock} としても同じです。判定の結果が true の場合は23-24行が有効になり、出荷ボタンが表示されます。 - 33行:th:if="!${#lists.isEmpty(prod.comments)}"
#lists ユーティリティを使って製品のコメント(prod.comments)の有無を判定します。コメントがあれば33-37行が有効になり、コメントの件数を表示するボタンとコメント一覧を表示します。 - 35行:th:each="cm : ${prod.comments}"
Product の comments の数だけ繰り返して、コメントをドロップダウンとして追加します。
sample05.html ビューの表示結果:
・選択変数式 *{...} の使い方
- 4行:th:object="${customer}"Customer オブジェクトを選択します。この <div> の範囲内で、選択式 *{..} を使って選択オブジェクトのプロパティを参照できます。HomeController.sample06() の
addAttribute("customer", new Customer(101, "顧客00001",
で登録した Customer インスタンスを参照します。
DateTime.now().minusMonths(13).toCalendar(Locale.JAPAN))); - 8行:th:text="*{id}"
${customer.id} と全く同じです。101を表示します。 - 11行:th:text="*{#calendars.format(customerSince,'yyyy/MM/dd')}"
*{customerSince} に #calenndars ユーティリティを使ってでフォーマットを設定する例です。 - 17行:th:text="'(' + *{id} + ')'"
18行:th:text="*{name + 'さん'}"
*{..} にテキストを追加する例です。前者の結果は "(101)"、後者の結果は"顧客00001さん"となります。 - 20行:th:utext="*{customerSince} < ${#calendars.create(2015,1,1)} ? '長期' : '短期'"
*{customerSince} と日付ユーティリティで生成した日付オブジェクトを比較して'長期'または'短期'を表示します。
sample06 ビューを表示します:
・変数式 ${...} を javascript の変数に代入する
- 20行:th:inline="javascript"
21行:var cust = [[${customer}]];
cust 変数に、HomeController.sample07() でモデルに追加した Customer インスタンスを代入します。 - 29行:JavaScript で、代入された Custom インスタンスを使用する例です。
sample07 ビューを表示します:
ソースコード:GitHub の bootThymeからダウンロードできます。