#17 Spring バリデーションの実行順序の変更

# #17 Spring バリデーションの実行順序の変更
前回は自分で設定したエラーメッセージが表示されるよう設定しました。
しかし、それだけでは不要なエラーメッセージも同時に表示されてしまうので、今回はエラーメッセージの表示順を設定します。

# 前提条件
この記事はSpringの最低限の知識が必要になります。
また、なるべく分かりやすく書くつもりですが、この記事の目的は自分の勉強のアウトプットであるため所々説明は省略します。

# 前回まで
前回の記事は以下になります。

https://qiita.com/Jackoguro/items/ddd68a48b1b99206b68c

# 構築環境
1. 各バージョン
Spring Boot ver 2.7.5
jquery ver 3.6.1
bootstrap ver 5.2.2
webjars-locator ver 0.46

2. 依存関係
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/f55dc9b5-e7b0-6bc6-45b5-27f1c4fd9771.png)

# 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/86fface6-374a-fc6c-4b4c-61f6f9bc9e18.png)
必須項目が入力されていない場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/f95c2893-d69d-380f-ffb4-150eed48bf05.png)
入力内容に誤りがある場合

# 今回行うこと
今回は以下の流れに沿って進めていきます。
1. GroupOrder.java, ValidGroup1.java, ValidGroup2.javaの作成
1. GroupOrder.javaに内容を記述
1. SignupForm.javaに内容を追加
1. SignupController.javaに内容を追加

## 1. GroupOrder.java, ValidGroup1.java, ValidGroup2.javaの作成
``src/main/java/com/example/form``の直下に、``GroupOrder.java``, ``ValidGroup1.java``, ``ValidGroup2.java``の3ファイルを作成します。
この3つのファイルは全てインターフェースです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/39b8c09d-bed8-408d-01be-f86f410d1c88.png)

## 2. GroupOrder.javaに内容を記述
次に``GroupOrder.java``内に先ほど追加した``ValidGroup1.java``, ``ValidGroup2.java``の2つのファイルを定義していきます。
```java:GroupOrder.java
package com.example.form;

import javax.validation.GroupSequence;

@GroupSequence({ ValidGroup1.class, ValidGroup2.class })
public interface GroupOrder {
}
```
ここでは``@GroupSequence({ ValidGroup1.class, ValidGroup2.class })``をクラスに付与します。
``@GroupSequence``アノテーションはバリデーションの順番を設定することができます。
左から設定されたインターフェースの順番でバリデーションを行います。

## 3. SignupForm.javaに内容を追加
Formクラスのバリデーションと先ほど登録したバリデーションの順番を紐付けて行きます。
```java:SignupForm.java

// 省略

@Data
public class SignupForm {
	
	@NotBlank(groups = ValidGroup1.class)
	@Email(groups = ValidGroup2.class)
	private String userId;
	
	private Integer phoneNumber;
	
	private Integer postal1;

	private Integer postal2;
	
	private String address;
	
	@NotBlank(groups = ValidGroup1.class)
	private String userName;
	
	@NotBlank(groups = ValidGroup1.class)
	@Pattern(regexp="^(?=.*[A-Z])[a-zA-Z0-9_]+$", groups = ValidGroup2.class) // 少なくとも大文字が1つ含まれる
	@Length(min=8, max=24 , groups = ValidGroup2.class)
	private String password;
	
	@DateTimeFormat(iso=DateTimeFormat.ISO.DATE)
	@Past(groups = ValidGroup2.class) // 過去の日付
	private Date birthday1;
	
	@DateTimeFormat(pattern="yyyy/MM/dd")
	private Date birthday2;
	
	@Min(value=5, groups = ValidGroup2.class)
	@Max(value=100, groups = ValidGroup2.class)
	private Integer age;
	
	private MultipartFile accountIcon;
	
	private Integer gender;
}
```
順番として、
1. 必須入力の確認
1. 入力内容の確認

の順で振り分けています。
``ValidGroup1``のチェックが全てOKだった場合、ValidGroup2のチェックが行われます。
下記の画像の場合、パスワードは``aaaaaaaa``なので、大文字を最低一文字含めないといけない要件を満たしていません。
しかし、エラーメッセージが出力されないのはユーザーIDとユーザー名がまだ``ValidGroup1``を満たしていないからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/72ccf6c4-85e6-f621-743e-92a22902504a.png)

## 4. SignupController.javaに内容を追加
```java:SignupController.java

// 省略

	/* ユーザー登録処理 */
	@PostMapping("/signup")
	public String postSignup(Model model, Locale locale, 
			@Validated(GroupOrder.class) @ModelAttribute SignupForm form,
			BindingResult bindingResult) {
		// 入力チェック
		if(bindingResult.hasErrors()) {
			// エラーが発生したので登録画面に戻る
			return getSignup(model, locale, form);
		}
	}
}
```
```java
// 変更前
public String postSignup(Model model, Locale locale, @Validated @ModelAttribute SignupForm form, BindingResult bindingResult) { ...

// 変更後
public String postSignup(Model model, Locale locale, @Validated(GroupOrder.class) @ModelAttribute SignupForm form, BindingResult bindingResult) { ...
```
``@Validated``アノテーションに``GroupOrder.class``を追加することでバリデーションの実行順を設定することができます。

# 最後に
以上でバリデーションに順番を付けることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/86fface6-374a-fc6c-4b4c-61f6f9bc9e18.png)
必須項目が入力されていない場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/f95c2893-d69d-380f-ffb4-150eed48bf05.png)
入力内容に誤りがある場合