search
LoginSignup
26

More than 1 year has passed since last update.

【Java】Spring Boot 2.3.1でバリデーションをつけていく記事

はじめに

こんにちは!ゼロからJavaであそぶシリーズ第4弾です。いま名前つけました。

前回までの記事はこちら↓

  1. macでSTSの環境構築
  2. Spring BootでHelloWorld
  3. Spring Bootでエコーアプリケーション作成

今回は、前回作ったエコーアプリケーションに、バリデーションをつけていこうと思います。

もょもと.gif

現状、文字列も数字も環境依存文字も、何文字でも入れられてしまうガバ状態なので、怪文書を送ると以下のように表示崩れが発生してしまいます。

スクリーンショット 2020-07-21 0.26.28.png

怖い。
名前にハテナが並んでると不穏な雰囲気になっちゃいますね。文字化けかな?
ゼロが画面幅を突き破ってしまっているのもなんか嫌ですね。

そこで今回は、何かのサービスのユーザーネームっぽく、以下の要件でバリデートするようにしちゃおうと思います。エラーの場合同じ画面内でエラーメッセージを出すイメージです。

  • 使用可能文字種:半角英数のみ
  • 文字数制限:4文字以上

完成品は以下のような形です。
(背景色を目に優しい色に変えました)

画面収録 2020-07-21 23.39.15.mov.gif

使用環境とバージョン

  • macOS Catalina
  • jdk14.0.1
  • JUnit5
  • Maven 3.6.3_1
  • STS 4.6.1
  • Spring Boot 2.3.1
  • spring-boot-starter-thymeleaf-2.3.1

フォームクラスにアノテーションでバリデーションを実装

フォームクラスに以下のアノテーションを追加しました。

  • @NotBlank:nullまたは空文字でないこと1をチェックできます
  • @Size:属性minまたはmaxを使用して最小値・最大値を指定できます
  • @Pattern:属性値regexpで正規表現のパターン文字列を指定できます。今回は半角英数のみを許容する正規表現を使用しました
EchoForm.java
package com.example.form;

import java.io.Serializable;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;

public class EchoForm implements Serializable {
    private static final long serialVersionUID = 1L;
    @NotBlank
    @Size(min = 4)
    @Pattern(regexp = "[a-zA-Z0-9]*") //英数字であること
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

コントローラークラスにエラー時の分岐追加

変更を加えたechoメソッドのみ記述します。
変更点は以下2点です。

  • 引数にBindingResultクラスを追加しました。BindingResultには入力チェック結果が入っています。入力チェックの実行とBindingResultの生成はフレームワークが担ってくれる部分ですので、実装の必要はありません。(Spring徹底入門より)
  • エラー時の分岐を追加しました。 アノテーションによるチェックでエラーが発生した場合、「Hello ${ユーザーネーム}」の画面に行ってほしくないため、同じページをリターンするように変更しています。
EchoController.java
@RequestMapping(value = "echo", method = RequestMethod.POST)
    public String echo(@Validated EchoForm echoForm, BindingResult result, Model model) {
        if (result.hasErrors() ) {
            model.addAttribute("name", echoForm.getName());
            return "index";
        }
        model.addAttribute("name", echoForm.getName());
        return "echo";
    }

index.htmlにエラー時のテキスト追加

エラーが出た際だけ、以下のように赤字のエラーメッセージを表示するようにしたいんですよね…
これ、Springならできちゃいます!

スクリーンショット 2020-07-21 23.26.59.png

前回既にフォームオブジェクトをバインディングしているので、echoFormのエラー情報を取得してThymeleafにぶち込みHTMLを作ることができてしまうのです。
Springすごい。Thymeleafすごい。

form部分のみ記載します。
spanで囲っている場所で、オブジェクトがエラーである場合のみエラーメッセージを表示するようにしてあります2。具体的に言うと、th:errors属性にフォームオブジェクトのプロパティを設定しているため、指定したプロパティに対するエラーメッセージのみ表示されるようになっています。
エラーメッセージが複数ある場合は自動的に<br />が入る仕様です。ありがたい。

index.html
<form th:object="${echoForm}" th:action="@{/echo}" method="POST">
        <div>ユーザーネームを入れてください</div>
        <div>(半角英数4文字以上)</div>
        <div>
            <input type="text" th:field="*{name}" /> 
            <button>送信します</button>
        </div>
        <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" style="color: red"></span>
</form>

エラー文言の日本語化

実は、ここまでの実装で実行すると、エラーメッセージがアノテーションのデフォルトメッセージ(英語)になってしまいますので、エラーが以下のようになってしまいます。

スクリーンショット 2020-07-21 23.52.09.png

これはちょっと嫌ですね…上はまだオシャレなエラーメッセージ❤️で通せるかもですけど、sizeの数字に関してはユーザーから見たら意味不明ですものね…
ここは日本語のエラーメッセージに直しましょう!

Spring MVCによるBean Validationのエラーメッセージは、propertiesファイルに定義するのが望ましいようです。いくつか方法があるようですが、クラスパス直下にValidationMessages.propertiesを作成する方法が分かりやすかったので、そちらを採用しました。

resources配下にValidationMessages.propertiesを新規作成します。

スクリーンショット 2020-07-22 0.29.58.png

中身は、使用したアノテーションのメッセージを書き換えるだけのシンプルな実装です。

ValidationMessages.properties
org.hibernate.validator.constraints.NotBlank.message=入力必須です。
javax.validation.constraints.Size.message=4文字以上でなくてはいけません。
javax.validation.constraints.Pattern.message=半角英数のみ有効です。

ちなみに、上記をただValidationMessages.propertiesに貼り付けると、日本語入力してエンターを押すだけで自動的に以下のようになってしまいました…Spring Bootの標準BeanがUTF-8でないためマルチバイト文字で文字化けしてしまうようです

ValidationMessages.properties
org.hibernate.validator.constraints.NotBlank.message=\u5165\u529B\u5FC5\u9808\u3067\u3059\u3002
javax.validation.constraints.Size.message=4\u6587\u5B57\u4EE5\u4E0A\u3067\u306A\u304F\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002
javax.validation.constraints.Pattern.message=\u534A\u89D2\u82F1\u6570\u306E\u307F\u6709\u52B9\u3067\u3059\u3002

こちらのQiitaのコメント欄でも言及があったのですが、自分もSpring 2系でJava11以上だからか、ファイルのプロパティでUTF-8にすればアプリケーションでも問題なく作動しました。
ファイルを右クリック > プロパティ > ResourceのText file encodingをデフォルトからUTF-8に変更するだけです。

スクリーンショット 2020-07-22 0.58.50.png

これでファイルを保存しようとすると以下警告が出ますが、Save as UTF-8で問題なく作動しました。

スクリーンショット 2020-07-22 0.50.06.png

これで、以下のように日本語のメッセージになりました!

スクリーンショット 2020-07-22 0.41.48.png

おわりに

今回はエラー時のテキスト追加部分のThymeleaf記法と、ValidationMessages.propertiesの日本語化でちょっと苦労しました!今回紹介した方法はSpring 1系だと怪しいので、適宜調べてみてください。

お読みいただき、ありがとうございました!


  1. nullのみチェックするには@NotNullを使用します 

  2. こちらのページの実装を参考にしました。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
26