【Thymeleaf】エラー表示を画面に出す方法(例:バリデーション)
新人
「フォームに入力したとき、入力ミスがあるときに画面にエラーを出したいんですけど、どうすればいいですか?」
先輩
「それなら、ThymeleafとSpringのバリデーション機能を組み合わせると簡単に実現できるよ。エラーメッセージを画面に出す方法を一緒に見ていこうか。」
新人
「エラーの出し方って、テンプレートファイルに直接書くんですか? それともJavaコード側で処理するんですか?」
先輩
「実は両方必要なんだ。バリデーションの設定はJavaで行い、表示はThymeleafで書くことで、初心者でも扱いやすい構成になるよ。」
1. 入力エラーとは何か?
Webフォームを使った入力画面では、ユーザーが誤った形式で情報を送信してくることがあります。たとえば、名前が空欄、メールアドレスの形式が正しくない、パスワードが短すぎるといった場合です。これらは入力エラーと呼ばれ、適切に処理しないとシステムに不正なデータが登録されてしまう可能性があります。
そこで必要になるのがバリデーションです。バリデーションとは、ユーザーが入力した値が正しいかどうかを検証する仕組みのことで、JavaとSpringではアノテーションを使って簡単に定義できます。
例えば、名前の入力が必須である場合、エンティティクラスのフィールドに@NotBlankを付けることで、空欄をエラーとして判定できます。この仕組みは、初心者にとっても習得しやすく、保守性の高いコードを書くことができるようになります。
2. バリデーションとは?
ここでは、SpringとThymeleafを使って、入力チェック(バリデーション)を実装するための基本的な流れを解説します。まずは、ユーザーが入力する内容を保持するモデルクラス(フォームクラス)を作成し、そこにアノテーションを使って制約をつけます。
次の例では、ユーザー登録画面を想定して、名前と年齢に対してバリデーションを設定しています。
package com.example.demo.form;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class UserForm {
@NotBlank(message = "名前を入力してください")
private String name;
@Min(value = 18, message = "18歳以上である必要があります")
private int age;
// getter と setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
上記のように、@NotBlankや@Minといったバリデーション用アノテーションを使って、入力条件を指定します。それぞれのアノテーションには、違反時に表示するエラーメッセージも設定できます。
次に、@Controllerを使ったSpringのコントローラクラスで、フォームからの入力を受け取る処理を記述します。Pleiades+Gradle構成で開発する場合、Spring MVCを使って以下のように記述できます。
package com.example.demo.controller;
import com.example.demo.form.UserForm;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@GetMapping("/user")
public String showForm(UserForm userForm) {
return "userForm";
}
@PostMapping("/user")
public String submitForm(@Valid UserForm userForm, BindingResult result, Model model) {
if (result.hasErrors()) {
return "userForm";
}
model.addAttribute("message", "登録が完了しました!");
return "userSuccess";
}
}
@Validはフォームクラスに設定されたバリデーションを有効にするアノテーションで、BindingResultはエラーの内容を受け取るために必要です。この2つは、必ずセットで使い、順番も重要です。@Validの直後にBindingResultを置かないと、正しく動作しません。
このようにして、ThymeleafとSpringの連携により、初心者でも簡単に入力エラーを処理し、ユーザーにわかりやすくエラーを表示する画面が作れます。
次回は、画面側でThymeleafを使ってエラーメッセージをどのように表示するのか、具体的なテンプレートファイルの例を見ながら解説していきます。
3. バリデーションのエラーメッセージをコントローラで受け取る方法
SpringとThymeleafでフォームを扱う場合、入力チェックに失敗したときに表示するエラーメッセージをコントローラで受け取る必要があります。そのために使用するのがBindingResultクラスです。
フォームの送信時、@Validアノテーションを使ってバリデーションを実行し、続けてBindingResult型の引数を受け取ることで、エラーの有無を確認できます。
具体的には、以下のように記述します。
@PostMapping("/user")
public String submitForm(@Valid UserForm userForm, BindingResult result, Model model) {
if (result.hasErrors()) {
return "userForm";
}
model.addAttribute("message", "登録が完了しました!");
return "userSuccess";
}
hasErrors()メソッドは、バリデーションエラーがあるかどうかを判定します。ここでエラーがあれば再度入力画面に戻り、Thymeleafでエラーメッセージを表示させる処理につながります。
4. Thymeleafテンプレートでエラーを表示する方法
次に、Thymeleafを使ってエラーメッセージを画面に出力する方法を説明します。テンプレートファイル(例:userForm.html)では、フォームの各入力項目に対してエラー表示の記述を行います。
まず、基本的なテンプレート構成は以下のようになります。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ユーザー登録フォーム</title>
</head>
<body>
<h1>ユーザー登録</h1>
<form th:action="@{/user}" th:object="${userForm}" method="post">
<div>
<label for="name">名前:</label>
<input type="text" id="name" th:field="*{name}">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></div>
</div>
<div>
<label for="age">年齢:</label>
<input type="number" id="age" th:field="*{age}">
<div th:if="${#fields.hasErrors('age')}" th:errors="*{age}" class="text-danger"></div>
</div>
<button type="submit">送信</button>
</form>
</body>
</html>
このように、th:errorsとth:ifを組み合わせることで、指定したフィールドにエラーがある場合だけ、メッセージを画面に出力できます。これにより、ユーザーはどの項目に問題があるのかを明確に把握できます。
th:fieldは、Thymeleafのth:objectで指定されたモデルオブジェクト(この場合はuserForm)のプロパティとバインドするための構文です。初心者でも視覚的にエラーが確認できるようにするには非常に有効です。
5. フォーム入力とエラーの連携
Thymeleafを使った入力フォームでは、バリデーションエラーが発生した場合でも、入力内容を保持したまま再表示することができます。これにより、ユーザーは入力ミスを修正するだけでよく、もう一度全てを入力し直す必要がありません。
以下はフォームの入力項目が再表示される仕組みを支えるテンプレートの一例です。
<form th:action="@{/user}" th:object="${userForm}" method="post">
<label for="name">名前:</label>
<input type="text" id="name" th:field="*{name}">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></div>
<label for="age">年齢:</label>
<input type="number" id="age" th:field="*{age}">
<div th:if="${#fields.hasErrors('age')}" th:errors="*{age}" class="text-danger"></div>
<button type="submit">登録</button>
</form>
th:object="${userForm}"により、フォーム全体がバインドされ、th:field="*{name}"などで対応するプロパティの値を保持したまま再表示されます。エラーが発生しても前回入力された値が消えないのは、ユーザーにとって大きなメリットです。
また、テンプレートにて各フィールドごとのth:errorsを使うことで、具体的なエラーメッセージを表示できます。これにより、初心者でもどこを修正すべきかがすぐに分かる画面になります。
Thymeleafのテンプレートエンジンは、フォームのバインドとエラー表示の処理が非常にスムーズに行える設計となっているため、Springアプリケーション開発では広く使われています。フォームとエラーの連携を丁寧に構築することで、よりユーザーフレンドリーなWebアプリケーションに近づくことができます。
次回は、よくあるつまずきポイントや、エラー表示で注意すべき点、そして実務での活用ノウハウについて詳しく見ていきましょう。
6. よくあるミスとその対処法
SpringとThymeleafでフォームバリデーションを行う際、初心者がよくつまずくポイントがいくつかあります。ここでは代表的なミスとその解決方法を紹介します。
まず最も多いのが、@Validアノテーションの付け忘れです。フォームクラスにバリデーションアノテーションを付けていても、コントローラで@Validを付けなければエラーは発生しません。
// 誤り(@Valid が無い)
@PostMapping("/user")
public String submit(UserForm userForm, BindingResult result) {
// バリデーションが機能しない
...
}
このように、@Validを省略するとSpringは入力チェックを実行しないため、必ず付けるようにしましょう。
次によくあるのが、BindingResultの順番の間違いです。@Validの直後にBindingResultを記述しないと、エラー情報が取得できません。
// 正しい順番
@PostMapping("/user")
public String submit(@Valid UserForm userForm, BindingResult result) {
...
}
さらに、テンプレートでのth:fieldのミスもありがちなエラーです。たとえば、th:objectでバインドしているにもかかわらず、th:fieldを使わずにth:valueで書いてしまうと、エラー表示が連携しません。
これらのポイントは、初心者がThymeleafやSpringを扱ううえで必ず通る道ですので、落ち着いて見直す習慣をつけましょう。
7. 実務で使える開発のコツ
実際の現場では、ThymeleafとSpringのバリデーションを活用するにあたり、効率的な開発の工夫が求められます。ここでは代表的な工夫を紹介します。
まずおすすめなのが、共通エラーパーツの作成です。Thymeleafではフラグメントを使ってテンプレートを共通化できます。エラー表示用のフラグメントを作っておけば、各画面で再利用できます。
<!-- fragments/error.html -->
<div th:fragment="fieldError(fieldName)">
<div th:if="${#fields.hasErrors(fieldName)}" th:errors="*{__${fieldName}__}" class="text-danger"></div>
</div>
これを各テンプレートで以下のように呼び出すことで、記述量を減らしつつ一貫性のあるエラー表示が可能になります。
<div th:replace="fragments/error :: fieldError('name')"></div>
また、バリデーションの設計ルールをあらかじめ決めておくことも大切です。たとえば、必須項目には常に@NotBlankを使う、数値チェックには@Minと@Maxを併用する、といったルールを整備しておくとチーム開発でも品質が安定します。
実務では、フォームの入力チェックがユーザー体験に直結します。そのため、丁寧に設計されたバリデーション処理は、システム全体の信頼性にもつながります。
8. 今後の開発でバリデーションを正しく使うために意識すべきこと
最後に、今後ThymeleafとSpringを使ったWebアプリケーションを開発していく際に、バリデーションを正しく活用するために覚えておくべきポイントを整理します。
まず第一に、ユーザー目線でのエラー表示を心がけることが大切です。技術的に正しいだけでなく、誰が見ても理解できるメッセージを表示するようにしましょう。たとえば「名前は必須です」と「このフィールドは無効です」では、前者の方が圧倒的に分かりやすいです。
次に、バリデーションロジックはドメインルールと紐づけて設計することです。例えば「年齢は18歳以上」という条件は、システムの仕様に基づいて設定すべきであり、アノテーションもその意図が伝わるように活用しましょう。
さらに、テンプレートエンジンThymeleafとの連携を意識した設計を心がけることで、画面とサーバのバリデーション結果が自然につながる仕組みが作れます。
初心者のうちは難しく感じるかもしれませんが、実際に手を動かしてバリデーションの流れを理解することで、フォームの作成や画面エラー表示がどんどん上達していきます。
また、検証対象の拡張性も考慮して、Bean Validationを自作アノテーションで拡張する方法もあります。慣れてきたら、グループバリデーションや条件付きバリデーションにも挑戦してみるとよいでしょう。
ThymeleafとSpringのバリデーションを活用すれば、ユーザーに優しいフォーム設計と、高い保守性を持つアプリケーションを構築できます。日々の開発の中で少しずつ改善を重ねていけば、より良いシステムを作る力が自然と身についていくはずです。