プロジェクト

全般

プロフィール

Spring MVC with Thymeleaf

はじめに

Spring MVCのView部分にThymeleafを使用したサンプルプログラムを作成します。
Spring_MVC のViewをJSPからThymeleafに置き換えたものになります。
Thymeleafは、HTMLで記述しますが、動的な部分は 属性に記述するため、ThymeleafのHTMLファイルを直接Webブラウザで表示した際に動的な動き以外はほぼ表示することができます。

リクエスト 処理するコントローラ 処理後に表示するビュー
GET / WelcomeController index.html
GET /echo EchoController input.html
POST /echo output.html

Hello worldの表示

まず、SpringBootのGradleプロジェクト作成と、Hello worldを表示する次の部分を実装します。

リクエスト 処理するコントローラ 処理後に表示するビュー
GET / WelcomeController index.html

新規プロジェクト作成

IntelliJ IDEA から、Spring Bootプロジェクトを生成します。

依存関係に、Spring WebとThymeleafをチェックします。

生成される build.gradle.ktsの依存関係定義は次です。

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
    implementation("org.springframework.boot:spring-boot-starter-web")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

画面の作成

HTMLで、Hello worldメッセージを表示するビューを作成します。

.
└─src
    ├─main
    │  ├─java
    :    :
    │  └─resources
    │      ├─static
    │      └─templates
                └ index.html

SpringBoot の Spring Initializrでプロジェクトを生成し、Thymeleafを使用する設定にすると、自動でビューのテンプレートのディレクトリやファイル拡張子などが設定されます。

index.html

まずは動的要素(Thymeleaf要素)のない素のHTMLを記述します。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Welcome</title>
</head>
<body>
<h1>Hello Thymeleaf World!</h1>
</body>
</html>

WelcomeController.java

ルートパスにHTTPリクエストされると、indexビューを表示するコントローラーを作成します。

.
└── src
    ├── main
        ├── java
            └── com
                └── torutk
                    └── spring
                        └── echo
                            └── WelcomeController.java
package com.torutk.spring.echo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WelcomeController {

    @RequestMapping("/")
    public String home() {
        return "index";
    }
}

コントローラーのメソッドの戻り値にindexの文字列を返却すると、index.htmlのテンプレートファイルを変換した結果がブラウザに送信されます。今回は、index.htmlにはまだThymeleafの動的要素を記述していないので、ほぼそのままのHTMLがブラウザに渡ります。

ビルド

Gradleの bootRunタスクを実行すると、ビルド後実行されます。

2025-04-30T21:56:24.846+09:00  INFO 28860 --- [echo] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'

実行

localhostの8080ポートにアクセスすると、index.htmlの内容が表示されます。

入力画面の追加

index.htmlをThymeleaf仕様に修正

<html lang="en" xmlns:th="http://www.thymeleaf.org">
  :
<ul>
  <li><a th:href="@{/echo}">Echo Application</a></li>
</ul>

html要素の属性に、Thymeleafの名前空間を定義します。
リンク要素に、th:href でリンク先をコンテキストパスより下の要素を指定します。実行時にコンテキストパスとth:hrefで指定したパスが結合されたリンクが生成されます。

input.htmlを作成

入力フォームを持つHTMLテンプレートファイルを作成します。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Input Message</title>
</head>
<body>
<h2>入力画面</h2>
<form action="./output.html" th:action="@{/echo}" th:object="${echoForm}" method="POST">
  <div>テキストを入力してください:</div>
  <div>
    <input type="text" name="text" th:field="*{text}" /><br />
    <span th:if="${#fields.hasErrors('text')}" 
          th:errors="*{text}">textのエラーメッセージ</span>
  </div>
  <div>
    <button type="submit">送信</button>
  </div>
</form>
</body>
</html>
  • form要素の属性 th:action で、アクション先のURLを生成
  • form要素の属性 th:object で、オブジェクト(ここではechoForm データクラス)を選択。formの子要素で選択したオブジェクトに対する操作をアスタリスク構文で指定可能
  • input要素の属性 th:field で、データと入力フィールドの値をバインディング、アスタリスク構文でtextを指定しているので、form要素の th:object で選択したechoFormのtextフィールとバインディング
  • #fields は、現在のフォームのエラーをチェックするなどの関数を提供。
  • th:errorsはエラーメッセージを動的に生成

実行

HTTP GET / の結果 HTTP GET /echo の結果 formに入力 submit結果

入力チェック

フォームに入力した値をチェックするには、Spring MVCでは、JavaのBean Validationの仕組みを利用してフォームオブジェクト(EchoForm)のプロパティに入力チェックルールを指定します。

Bean Validationライブラリを使用

プロジェクト作成時に、IO > Validation にチェックを入れておくか、Gradleのdependenciesにvalidationを追記します。

build.gradle.ktsに追記

dependencies {
    :
    implementation("org.springframework.boot:spring-boot-starter-validation")

EchoFormに制約を記述

import jakarta.validation.constraints.NotEmpty;
  :
public class EchoForm implements Serializable {
    :
    @NotEmpty
    private String text;

フォームのフィールドの入力を必須とするときは、@NotEmptyを対応するフォームクラスのフィールドにアノテーション指定します。

EchoControllerにエラーチェックを記述

  @RequestMapping(method = RequestMethod.POST)
    public String echo(@Valid EchoForm form, BindingResult result) {
        if (result.hasErrors()) {
            return "echo/input";
        }
  • フォームのsubmitを受けるメソッドの引数に、BindingResutlを追記します。
  • BindingResultにエラーがあるかを問い合わせ、エラーがあれば再度入力画面を表示します。
  • 入力画面には、フィールドのエラーがあるときの表示が定義されています。

    実行して、テキストを空のまま送信ボタンを押すと、次のエラーメッセージが入力画面に表示されます。

少し応用

Thymeleafの表示

メッセージ定義の利用

MessageSourceに定義されたメッセージを読みだして表示に使用します。

デフォルトでは、src/main/resources/の下にあるプロパティファイル messages.properties およびロケール個別の messages_ja.properties などに記載のキー・値から、キーを指定して値を取り出し表示に使用します。

  • messages.properties
    top.greeting=Hello, Thymeleaf world!
    
  • index.html
    <h1 th:text="#{top.greeting}">Hello Thymeleaf World!</h1>
    

プロパティファイルにキー=値で定義しておき、HTML(Thymeleaf)で、th:text="#{top.greeting}" とキーを指定すると実行時にキーに対応する値に置き換えてくれます。

日本語ロケールのメッセージは、messages_ja.propertiesファイルに記述します。UTF-8で記述します。

  • messages_ja.properties
    top.greeting=こんにちは、Thymeleafの世界
    

IntelliJ IDEAで拡張子propertiesのファイルを作成すると、プロジェクト設定に定義されるエンコーディングで保存されます。デフォルトは、ISO-8859-1です。これは、昔のJavaはPropertyResourceBundleを使ってプロパティファイルを読み込む際にファイルのエンコーディングがISO-8859-1に規定されており、ラテン文字以外の文字を使用する場合、ユニコードエスケープ表記にする必要があった名残りです。Java 9以降では、PropertyResourceBundleはUTF-8エンコーディングで読み込むようになったので、プロパティファイルをUTF-8で記述することが可能となりました。IntelliJを使っている場合、[File]メニュー > [Settings] > [Editor] > [File Encodings] で、[Default encoding for property files] を UTF-8に変更します。

参考文献

Thymeleaf

Thymeleaf公式サイト


約1ヶ月前に更新