Spring Boot チェック処理

Spring Bootのチェック処理に順番をつけてみた

Spring Bootを利用したWEBアプリケーション上で、フォームクラスにアノテーションを指定することで、様々な単項目チェックを行うことができるが、そのアノテーションにgroups属性を指定することで、チェック処理の順番をつけることができる。

今回は、チェックを行うフォームクラスのアノテーションに、groups属性を指定してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事の実装が完了していること。

Spring BootのWEB画面上でチェック処理を実装してみた(ソースコード編)今回も、引き続きチェック処理を含むそのサンプルプログラムについて共有する。前回は、サンプルプログラムの完成イメージについて記載していたが...

サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。

コントローラクラスの内容は以下の通りで、loginメソッド内で、フォームクラスに定義されたチェックを行うようになっている。また、チェックの順番を有効にするために、引数のフォームに「@Validated(All.class)」アノテーションを付与している。

package com.example.demo;

import com.example.demo.order.All;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

/**
 * コントローラクラス
 * 「@SessionAttributes(types = DemoForm.class)」により、
 * 生成したFormオブジェクトをセッションとしてもたせている
 */
@Controller
@SessionAttributes(types = DemoForm.class)
public class DemoController {

    /**
     * Formオブジェクトを初期化して返却する
     * @return Formオブジェクト
     */
    @ModelAttribute("demoForm")
    public DemoForm createDemoForm(){
        DemoForm demoForm = new DemoForm();
        return demoForm;
    }

    /**
     * ログイン画面に遷移する
     * @return ログイン画面へのパス
     */
    @GetMapping("/")
    public String index(){
        return "login";
    }

    /**
     * エラーチェックを行い、エラーが無ければメイン画面に遷移し、
     * エラーがあればログイン画面のままとする
     * @param demoForm Formオブジェクト
     * @param result バインド結果
     * @return メイン画面またはログイン画面へのパス
     */
    @PostMapping("/login")
    public String login(@Validated(All.class) DemoForm demoForm
            , BindingResult result){
        // formオブジェクトのチェック処理を行う
        if(result.hasErrors()){
            // エラーがある場合は、ログイン画面のままとする
            return "login";
        }
        // メイン画面に遷移する
        return "main";
    }

    /**
     * ログイン画面に戻る
     * @param sessionStatus セッションステータス
     * @return ログイン画面
     */
    @PostMapping(value = "/back")
    public String back(SessionStatus sessionStatus){
        // セッションオブジェクトを破棄する
        sessionStatus.setComplete();
        return "login";
    }

}

また、フォームクラスの内容は以下の通りで、IDとパスワードの入力チェックを行うようになっている。また、groups属性で何番目にチェックをするかを指定している。

package com.example.demo;

import com.example.demo.order.First;
import com.example.demo.order.Second;
import com.example.demo.order.Third;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;

/**
 * Formオブジェクトのクラス
 */
@Data
public class DemoForm {

    /** ID */
    // 必須指定・桁数は3桁・半角数字で入力可能とする
    // 必須チェックは1回目に、それ以外のチェックは2回目に行う
    @NotEmpty(groups = First.class)
    @Length(min = 3, max = 3, groups = Second.class)
    @Pattern(regexp = "^[0-9]+$"
           , message = "{validation.number}"
           , groups = Second.class)
    private String id;

    /** パスワード */
    // 必須指定・桁数は8~10桁・半角英数字で入力可能とする
    // 必須チェックは1回目に、桁数チェックは2回目に、
    // 半角英数字チェックは3回目にそれぞれ行う
    @NotEmpty(groups = First.class)
    @Length(min = 8, max = 10, groups = Second.class)
    @Pattern(regexp = "^[a-zA-Z0-9]+$"
           , message = "{validation.alpha-number}"
           , groups = Third.class)
    private String password;

}

さらに、フォームクラスの入力チェックのgroups属性で指定した順番を定義する各インタフェースの内容は以下の通りで、Allインタフェース内で、チェックの順番を定義している。

package com.example.demo.order;

public interface First {
}
package com.example.demo.order;

public interface Second {
}
package com.example.demo.order;

public interface Third {
}

また、チェック処理で使用しているエラーメッセージは、以下のプロパティファイルで定義している。

#メッセージ
javax.validation.constraints.NotEmpty.message={0}を入力してください。
org.hibernate.validator.constraints.Length.message
  ={0}は${min == max ? min += '桁で入力してください' 
     : min += '桁以上' += max += '桁以下で入力してください'}
validation.number={0}は半角数字で入力してください。
validation.alpha-number={0}は半角英数字で入力してください。

#フィールド名
id=ID
password=パスワード

なお、上記プロパティファイルでは、Lengthアノテーションを改行して表示しているが、実際は改行しない設定になっている。



さらに、ログイン画面とそのCSS,JSファイルの内容は以下の通りで、フォームクラスの入力チェックの結果を表示している。また、「パスワードを表示する」チェックボックスが選択された場合の動きを定義している。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link th:href="@{/login.css}" rel="stylesheet" type="text/css" />
    <script type="text/javascript" th:src="@{/login.js}"></script>
    <title>ログイン画面</title>
</head>
<body>
<form method="post" th:action="@{/login}" th:object="${demoForm}">
    <p>ID・パスワードを入力の上、「ログイン」ボタンを押下してください。</p>
    <ul>
        <li th:each="error : ${#fields.detailedErrors()}" class="errorMessage">
            <span th:text="${error.message}">ここにエラーメッセージを表示する</span>
        </li>
    </ul>
    <table border="0">
        <tr>
            <td align="left" valign="top">ID:</td>
            <td>
                <input type="text" maxlength="3" th:value="*{id}"
                       th:field="*{id}" th:errorclass="fieldError" />
            </td>
        </tr>
        <tr>
            <td align="left" valign="top">パスワード:</td>
            <td>
                <input type="password" maxlength="10" th:value="*{password}"
                       th:field="*{password}" th:errorclass="fieldError" />
            </td>
        </tr>
        <tr>
            <td align="left" valign="top" colspan="2">
                <input type="checkbox" id="pwCheck"
                       onclick="changePwType(this.checked)">パスワードを表示する
            </td>
        </tr>
    </table>
    <br/><br/>
    <input type="submit" value="ログイン" />
</form>
</body>
</html>
.errorMessage{
    color: #FF0000;
}
.fieldError{
    background-color: #FFCCFF;
}
'use strict';

// 「パスワードを表示する」チェックボックスが選択された場合の処理
function changePwType(pwCheck){
    const pwd = document.getElementById('password');
    if(pwCheck){
        // パスワードのテキストボックスのタイプをテキストにする
        pwd.setAttribute('type', 'text');
    }else{
        // パスワードのテキストボックスのタイプをパスワードにする
        pwd.setAttribute('type', 'password');
    }
}

また、メイン画面のHTMLは以下の通りで、ログイン後の画面の内容を定義している。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>メイン画面</title>
</head>
<body>
   メイン画面に遷移しました。<br/><br/>
<form method="post" th:action="@{/back}">
    <input type="submit" value="ログアウト"/>
</form>
</body>
</html>

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-check-order/demo



Code VillageはJavaScriptを中心としたサポート体制が充実したプログラミングスクールだったJavaScriptや、JavaScriptのフレームワーク「React」「Vue」を中心にオンラインで学習できるプログラミングスクール...

サンプルプログラムの実行結果

サンプルプログラムの実行結果は、以下の通り。

1) Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)/」にアクセスすると、以下のように、login.htmlの画面が表示されることが確認できる。
サンプルプログラムの実行結果_1

2) 何も指定せず「ログイン」ボタンを押下すると、以下のように、エラーメッセージが表示されることが確認できる。
サンプルプログラムの実行結果_2

3) IDのみ指定し「ログイン」ボタンを押下すると、以下のように、パスワードの必須チェック(1回目)でエラーになるため、IDの桁数・文字数チェック(2回目)のチェックが行われないことが確認できる。
サンプルプログラムの実行結果_3_1

サンプルプログラムの実行結果_3_2

4) ID・パスワード(いずれも2回目のチェックでエラーになる値)を指定し「ログイン」ボタンを押下すると、以下のようなエラーが発生することが確認できる。
サンプルプログラムの実行結果_4_1

サンプルプログラムの実行結果_4_2

5) ID・パスワードを指定し、「パスワードを表示する」チェックを押下すると、以下のように、パスワードが表示されることが確認できる。
サンプルプログラムの実行結果_5_1

サンプルプログラムの実行結果_5_2

6) ID(エラーでない値)、パスワード(3回目のチェックでエラーになる値)を指定し「ログイン」ボタンを押下すると、以下のようなエラーが発生することが確認できる。
サンプルプログラムの実行結果_6_1

サンプルプログラムの実行結果_6_2

7) ID・パスワード(いずれもエラーでない値)を指定し「ログイン」ボタンを押下すると、以下のように、メイン画面に遷移できることが確認できる。
サンプルプログラムの実行結果_7_1

サンプルプログラムの実行結果_7_2

要点まとめ

  • Spring Bootを利用したWEBアプリケーション上で、フォームクラスにアノテーションを指定することで、様々な単項目チェックを行うことができるが、そのアノテーションにgroups属性を指定することで、チェック処理の順番をつけることができる。