Thymeleaf は、Web および非 Web 環境で使用できる Java XML / XHTML / HTML5 テンプレートエンジンです。MVC ベースの Web アプリケーションのビュー層で XHTML / HTML5 を提供するのに適していますが、オフライン環境でも任意の XML ファイルを処理できます。完全な Spring Framework 統合を提供します。
開発環境#
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
依存関係の追加#
主に spring-boot-starter-thymeleaf
依存関係を追加します:
spring-boot-starter-thymeleaf
:Thymeleaf テンプレートエンジンの自動構成
<dependencies>
...
<!-- Thymeleaf Start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Thymeleaf End -->
...
</dependencies>
Thymeleaf の設定#
application.yml
spring:
thymeleaf:
cache: false # テンプレートキャッシュを有効にするかどうか、デフォルトは:true、開発時はキャッシュを無効にしないとリアルタイムページが見れません!
mode: HTML # テンプレートのモードを指定、デフォルトは:HTML
encoding: UTF-8 # テンプレートのエンコーディングを指定、デフォルトは:UTF-8
prefix: classpath:/templates/ # テンプレートのプレフィックスを指定、デフォルトは:classpath:/templates/
suffix: .html # テンプレートのサフィックスを指定、デフォルトは:.html
servlet:
content-type: text/html # Content-Type 値を指定、デフォルトは:text/html
org.thymeleaf.templatemode.TemplateMode
から、Thymeleaf
は 3.0.0
バージョンから HTML
を HTML5、LEGACYHTML5、XHTML、VALIDXHTML
の代わりに使用していることがわかります。もし 3.0.0
より前のバージョンを使用していて、非厳密な HTML を使用したい場合は、以下の設定を行う必要があります:
pom.xml
にnekohtml
依存関係を追加application.yml
にspring.thymeleaf.mode=LEGACYHTML5
を設定
詳細なプロパティ設定については、「Appendix A. Common application properties」の # THYMELEAF (ThymeleafAutoConfiguration)
モジュールのプロパティ紹介を参照してください。(TIPS:CTRL + F
で迅速に位置を特定)
テスト Controller の作成#
message
プロパティに値を設定し、リダイレクトする Controller を作成します。コードは以下の通りです:
IndexController.java
@Controller
public class IndexController {
@GetMapping(path = {"/", "index"})
public String indexPage(Model model) {
model.addAttribute("message", "Hello Thymeleaf!");
return "index";
}
}
テスト HTML ページの作成#
templates
ディレクトリに index.html
ファイルを作成し、html
タグ内で Thymeleaf 名前空間 xmlns:th="http://www.thymeleaf.org"
を宣言します。コードは以下の通りです:
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Thymeleaf</title>
</head>
<body>
<h1 th:text="${message}">Hello World!</h1>
</body>
</html>
ここでの重要なコードは:
xmlns="http://www.thymeleaf.org"
主に IDE が Thymeleaf 名前空間を認識できるようにするためのもので、タグ内に th:
を入力すると、IDE が対応する構文を提示し、開発が容易になります!このコードを追加しなくても Thymeleaf テンプレートエンジンのレンダリングやページの正常表示には影響しません。
テストアクセス#
起動に成功したら、http://127.0.0.1:8080 にアクセスすると、効果が確認できます:
アクセス結果:Hello Thymeleaf!
Thymeleaf の一般的な構文#
- JAVA ソースコードパス:TagsController.java
- HTML ソースコードパス:
templates
ディレクトリ
変数値の取得#
<p th:text="'Hello! ' + ${name} + '!'" >name</p>
変数値の取得には $
記号を使用します。JavaBean の場合は 変数名.属性名
方式で取得します。この点は EL
表現と同様です。
また、$
表現は th
タグ内にのみ記述でき、それ以外では機能しません。上記の例は th:text
タグの値で <p>...</p>
タグ内の値を置き換えています。p
内の元の値はフロントエンド開発時の表示用です。このようにして、フロントエンドとバックエンドの分離がうまく実現されています。
コンテンツ情報の出力:th:text
と th:utext
#
th:text
:プレーンテキストとして出力th:utext
:HTML タグとして出力し、ブラウザが正常にレンダリングします
HTML コード:
<body>
<h2 th:text="' th:text   » ' + ${content}">プレーンテキストとして出力</h2>
<h2 th:utext="'th:utext » ' + ${content}">HTML タグとして出力し、ブラウザが正常にレンダリングします</h2>
</body>
JAVA コード:
@GetMapping("/text-utext")
public String textAndutext(Model model) {
model.addAttribute("content", "<span style='color:red'>thymeleaf text output</span>");
return "text-utext";
}
URL の参照#
URL の処理は @{…}
構文を使用して行います:
HTML コード:
<body>
<ul>
<li>
<a th:href="@{https://github.com/{username}(username=${username})}">絶対パス 1</a>、
<a th:href="@{https://www.baidu.com}">絶対パス 2</a>
</li>
<li>
<a th:href="@{/}">相対パス</a>
</li>
<li>
<a th:href="@{/css/app.css}">コンテンツパス、デフォルトで static 下の CSS ファイルにアクセスします</a>
</li>
</ul>
</body>
JAVA コード:
@GetMapping("/refer-url")
public String referUrl(Model model) {
model.addAttribute("username", "y0ngb1n");
return "refer-url";
}
類似のタグには:th:href
と th:src
があります。
文字列の置換#
多くの場合、大きなテキストの中の特定の部分だけを置き換えたいことがあります。文字列の結合操作を通じて実現できます:
<p th:text="'Welcome to our application, ' + ${user.name} + '!'">
別のより簡潔な方法を使用できます:
<p th:text="|Welcome to our application, ${user.name}!|">
文字の置換は他の表現と組み合わせて使用することもできます:
<p th:text="${onevar} + ', ' + |${twovar}, ${threevar}|">
もちろん、この形式には制限があり、|…|
内には変数表現 ${…}
のみを含めることができ、他の定数や条件表現などは含めることができません。
HTML コード:
<body>
<p th:text="'Welcome to our application, ' + ${user.name} + '!'">
<p th:text="|Welcome to our application, ${user.name}!|">
<p th:text="${onevar} + ', ' + |${twovar}, ${threevar}|">
</body>
JAVA コード:
@GetMapping("replace-text")
public String replaceText(Model model) {
model.addAttribute("user", user);
model.addAttribute("onevar", "one");
model.addAttribute("twovar", "two");
model.addAttribute("threevar", "three");
return "replace-text";
}
演算子#
式内で各種算術演算子を使用できます。例えば +, -, *, /, %
:
th:with="isEven=(${user.age} % 2 == 0)"
論理演算子 >, <, <=, >=, ==, !=
も使用できます。唯一注意が必要なのは、<, >
を使用する際には HTML エスケープ文字を使用することです:
th:if="${user.age} > 1"
th:text="'Environment is ' + ((${env} == 'dev') ? 'Development' : 'Production')"
HTML コード:
<body>
<h2 th:text="|name: ${user.name}, age: ${user.age}, env: ${env}|"></h2>
<p th:with="isEven=(${user.age} % 2 == 0)">年齢は偶数です</p>
<p th:with="isEven=(${user.age == 18})">おや、まだ 18 ですか!</p>
<p th:if="${user.age} > 18">現在の年齢は 18 より大きいです</p>
<div th:class="${env} == 'dev' ? 'dev' : 'prod'"></div>
<p th:text="'現在の環境:' + ((${env} == 'dev') ? 'Development' : 'Production')"></p>
</body>
JAVA コード:
@GetMapping("/operator")
public String operator(Model model) {
model.addAttribute("user", user);
model.addAttribute("env", "dev");
return "operator";
}
条件判断#
th:if, th:unless
#
th:if
と th:unless
属性を使用して条件判断を行います。以下の例では、タグは th:if
の条件が成立した場合のみ表示されます:
<a th:href="@{/login}" th:if=${user == null}>ログイン</a>
<a th:href="@{/login}" th:unless=${user != null}>ログイン</a>
th:unless
は th:if
の正反対で、式の条件が成立しない場合にのみその内容が表示されます。
th:switch, th:case
#
複数の選択 Switch 構造をサポートしています:
<div th:switch="${user.role}">
<p th:case="'admin'">ユーザーは管理者です</p>
<p th:case="#{roles.manager}">ユーザーはマネージャーです</p>
</div>
デフォルト属性 default
は *
で表すことができます:
<div th:switch="${user.role}">
<p th:case="'admin'">ユーザーは管理者です</p>
<p th:case="#{roles.manager}">ユーザーはマネージャーです</p>
<p th:case="*">ユーザーは他の何かです</p>
</div>
メッセージ式:
#{...}
は、テキストの外部化、国際化または i18n とも呼ばれます。
HTML コード:
<body>
<a th:href="@{/login}" th:unless="${user == null}">ログイン</a>
<p th:if="${user != null}">ようこそ、<span th:text="|${user.name}(role: ${user.role})|">tony</span></p>
<div th:switch="${user.role}">
<p th:case="'admin'">ユーザーは管理者です</p>
<p th:case="#{roles.manager}">ユーザーはマネージャーです</p>
<p th:case="*">ユーザーは他の何かです</p>
</div>
</body>
JAVA コード:
@GetMapping("/condition")
public String condition(Model model) {
model.addAttribute("user", user);
return "condition";
}
ループ#
リストデータのレンダリングは非常に一般的なシナリオです。例えば、n 件のレコードをテーブルにレンダリングする必要がある場合、そのデータ集合は反復可能でなければなりません。th:each
タグを使用します:
HTML コード:
<body>
<table>
<tr>
<th>名前</th>
<th>年齢</th>
<th>管理者</th>
</tr>
<tr th:each="user : ${users}">
<td th:text="${user.name}">玉ねぎ</td>
<td th:text="${user.age}">22</td>
<td th:text="${user.role} == 'admin' ? #{true} : #{false}">はい</td>
</tr>
</table>
</body>
見ての通り、ループレンダリングされる要素(ここでは)に th:each
タグを追加する必要があります。th:each="prod : ${prods}"
は、集合変数 prods
を反復処理し、ループ変数は prod
で、ループ体内で式を通じてアクセスできます。
JAVA コード:
@GetMapping("/loop")
public String loop(Model model) {
List<User> users = new ArrayList<>(3);
users.add(user);
users.add(User.builder().name("tony").age(23).role("user").build());
users.add(User.builder().name("tom").age(21).role("user").build());
model.addAttribute("users", users);
return "loop";
}
詳細なタグの使用法については、「Thymeleaf の一般的な構文」、「Thymeleaf 参考手引き」を参照して、さらに多くのテクニックを解放してください 😜