【今更ながらSpring BootでWEB開発 #4】バリデーション

Web

今回の目標

前回は簡単なお問い合わせフォームを作って、入力したデータをサーバーサイドに送信する方法を説明しました。

【今更ながらSpring BootでWEB開発 #3】フォームの送信
今回は簡単なお問い合わせフォームを作成し、サーバーサイドに入力されたデータを送信する方法について説明していきます。Spring Bootではフォーム対応するクラスを利用することで楽に送信されたデータを扱うことができます。

今回は送信されたデータをサーバーサイドでチェックするためのバリデーションについて説明していきます。

前回作成したフォームをそのまま使うので、前回の記事をまだ見ていないという方は先にそちらをお読みください。

バリデーションの設定

お問い合わせフォームで入力する「name」、「email」、「contents」はそれぞれ次の条件を満たすものとします。

フィールド条件
name・入力必須
・64文字以内
email・入力必須
・128文字以内
・メールアドレス
contents・入力必須
・512文字以内

Spring Bootではアノテーションを使うことでフィールドの条件を定義することができます。例えば上記の条件を定義する場合は、InquiryForm.javaで定義しているフィールドに次のようにアノテーションを付与します。

@NotBlank
@Size(max = 64)
private String name;
  
@NotBlank
@Size(max = 128)
@Email
private String email;
  
@NotBlank
@Size(max = 512)
private String contents;

バリデーションに関するアノテーションには次のようなものがあります。型によって使用できるものが決まっていますがここでは割愛しています。

アノテーション説明
@AssertFalsefalseであることを検証する。
@AssertTruetrueであることを検証する。
@DecimalMaxDecimal型が最大値以下であることを検証する。
@DecimalMinDecimal型が最小値以上であることを検証する。
@Digits(integer= ,fraction=)数値の桁数が範囲内であることを検証する。
integerは整数、fractionは小数の最大桁数を意味する。
@Future未来の日付であることを検証する。
@Max数値が最大値以下であることを検証する。
@Min数値が最小値以上であることを検証する。
@NotNullNullでないことを検証する。
@NullNullであることを検証する。
@Past過去の日付であることを検証する。
@Pattern(regex= , flag=)指定した正規表現を満たすことを検証する。
@Size(min= , max= )文字数、またはCollectionなどの数が範囲内であることを検証する。
@Validネストしたクラスのバリデーションを実行する。
@CreditCardNumberクレジット番号が妥当か検証する。
@Emailメールアドレスが妥当(RFC2822)か検証する。
@Length(min=, max= )文字数の範囲を検証する。
@NotBlank空文字またはNullでないことを検証する。
@NotEmpty文字またはCollectionなどがNullまたは空でないことを検証する。
@Range(min= ,max= )数値の範囲を検証する。

 バリデーションの実行

フォームのクラスにバリデーションの設定ができたので、POSTでリクエストを受け取ったときにバリデーションを実行するようにします。

Spring Bootでは「@Validated」を次のように付与することでバリデーションが実行されるようになります。またバリデーションの結果は「BindingResult」に反映されるようになっており、引数に追加することで参照できます。

@PostMapping("/confirm")
public String confirm(@Validated InquiryForm inquiryForm, BindingResult result) {
  if (result.hasErrors()) {
    return "inquiry/index.html";
  }
  return "inquiry/confirm.html";
}

1つでもバリデーションに違反した場合は、元のフォーム画面を再度表示するようにします。

エラーメッセージの表示

それではフォームの画面に戻った際にエラーメッセージを表示するようにします。次のように各入力欄の下にエラーメッセージを表示するようにします。

Thymeleafでエラーメッセージを参照するには、「th:errors」を設定します。

<form method="post" action="/inquiry/confirm" th:object="${inquiryForm}">
  <div class="field">
    <label for="name">お名前</label><span class="tag">必須</span><br />
    <input type="text" id="name" name="name" th:value="*{name}">
    <p th:errors="*{name}" class="error-message"></p>
  </div>
  <div class="field">
    <label for="email">メールアドレス</label><span class="tag">必須</span><br />
    <input type="text" id="email" name="email" th:value="*{email}">
    <p th:errors="*{email}" class="error-message"></p>
  </div>
  <div class="field">
    <label for="contents">お問い合わせ内容</label><span class="tag">必須</span><br />
    <textarea id="contents" name="contents" cols="30" rows="10" th:text="*{contents}"></textarea>
    <p th:errors="*{contents}" class="error-message"></p>
  </div>
  <input type="submit" value="確認ページへ">
</form>

エラーメッセージにはバリデーションで設定されているデフォルトメッセージが表示されます。実際に展開されたDOMを確認すると、エラーが無いときはエラーメッセージとして設定しているpタグは展開されておらず、エラーがある場合にのみ展開されます。

その他に、エラーがあるときに特定の要素を表示したい場合は「#fields」を使用します。

<form method="post" action="/inquiry/confirm" th:object="${inquiryForm}">
 <p th:if="${#fields.hasErrors('name')}">お名前にエラーがあります。</p>
 <!-- 省略 -->
</form>

#fieldsを使用する場合は、親要素に検証対象のオブジェクトをth:objectで指定する必要があります。今回の例では、「inquiryFormオブジェクトのnameフィールドにはエラーがあるか?」という条件を設定していることになります。

#fieldsによる条件は要素の表示・非表示だけでなく、クラスの付与などにも使用できます。

<input type="text" id="name" name="name" th:value="*{name}" th:class="${#fields.hasErrors('name')} ? border-red">

エラーメッセージのカスタマイズ

今のままだとデフォルトのエラーメッセージが表示されてしまうため実用的ではありません。デフォルトメッセージを書き換えるには、次のようにバリデーションで設定したアノテーション内にmessageを追加します。

@NotBlank(message = "お名前を入力してください")
@Size(max = 64, message="お名前は64文字以内で入力してください")
private String name;
  
@NotBlank(message = "メールアドレスを入力してください")
@Size(max = 128, message = "メールアドレスは128文字以内で入力してください")
@Email(message = "メールアドレスを正しく入力してください")
private String email;
  
@NotBlank(message = "お問い合わせ内容を入力してください")
@Size(max = 512, message = "お問い合わせ内容は512文字以内で入力してください")
private String contents;

別の方法として、「ValidationMessages.properties」を作成することで各アノテーションのデフォルトメッセージを変更することができます。src/main/resourcesの直下、application.propertiesと同じところにValidationMessages.propertiesを作成し、次のようにアノテーションのデフォルトメッセージを設定します。

javax.validation.constraints.NotBlank.message=必須入力です
javax.validation.constraints.Size.message=文字数が範囲外です
javax.validation.constraints.Email.message=メールアドレスが正しくありません

作成したpropertiesファイルやプロジェクト自体のエンコードによって文字化けが発生してしまいます。今回はすべてUTF-8に設定してある想定で説明しています。

あとがき

今回はバリデーションについて説明しました。Spring Bootではアノテーションを活用することで簡単にバリデーションを行うことができます。

アノテーションを自作することでカスタムバリデーションを作ることも可能ですが、今回は割愛します。

 

- Spring Bootのおすすめ書籍はコチラ -

コメント

タイトルとURLをコピーしました