y0ngb1n

Aben Blog

欢迎来到我的技术小黑屋ヾ(◍°∇°◍)ノ゙
github

Spring Boot 2.0 と Thymeleaf モジュールエンジンの統合

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 から、Thymeleaf3.0.0 バージョンから HTMLHTML5、LEGACYHTML5、XHTML、VALIDXHTML の代わりに使用していることがわかります。もし 3.0.0 より前のバージョンを使用していて、非厳密な HTML を使用したい場合は、以下の設定を行う必要があります:

  • pom.xmlnekohtml 依存関係を追加
  • application.ymlspring.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

アクセス結果:Hello Thymeleaf!


Thymeleaf の一般的な構文#

  • JAVA ソースコードパス:TagsController.java
  • HTML ソースコードパス:templates ディレクトリ

変数値の取得#

<p th:text="'Hello! ' + ${name} + '!'" >name</p>

変数値の取得には $ 記号を使用します。JavaBean の場合は 変数名.属性名 方式で取得します。この点は EL 表現と同様です。

また、$ 表現は th タグ内にのみ記述でき、それ以外では機能しません。上記の例は th:text タグの値で <p>...</p> タグ内の値を置き換えています。p 内の元の値はフロントエンド開発時の表示用です。このようにして、フロントエンドとバックエンドの分離がうまく実現されています。

コンテンツ情報の出力:th:textth:utext#

  • th:text:プレーンテキストとして出力
  • th:utext:HTML タグとして出力し、ブラウザが正常にレンダリングします

th と th

HTML コード:

<body>
  <h2 th:text="' th:text &nbsp » ' + ${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 の処理は @{…} 構文を使用して行います:

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:hrefth: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} &gt; 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}  &gt; 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:ifth:unless 属性を使用して条件判断を行います。以下の例では、タグは th:if の条件が成立した場合のみ表示されます:

<a th:href="@{/login}" th:if=${user == null}>ログイン</a>
<a th:href="@{/login}" th:unless=${user != null}>ログイン</a>

th:unlessth: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 参考手引き」を参照して、さらに多くのテクニックを解放してください 😜


参考資料#

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。