0
0

SpringBoot の Validation 簡易メモ

Last updated at Posted at 2024-06-23

SpringBoot で Validation 使った時のの簡易メモ
良いやり方は模索中。。。

実行環境

  • Windows11
  • Pleiades 2024 Full Edition
  • Maven v3.9.6
  • SpringFramework Boot v3.3.0
  • Java v21
  • spring-boot-starter-thymeleaf
  • spring-boot-starter-web
  • spring-boot-starter-validation

プロジェクト作成

  • Spring Boot DevTools
  • Spring Web
  • Lombok
  • Thymeleaf
  • Validation

Validation で追加された依存関係は以下

pom.xml
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

バリデーションするDTO作成

入力フォームで使う変数を持ったオブジェクト
クラス変数にバリデーションをアノテーションで追加

簡単な使用例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class XxxDto {

	@NotNull
	private Integer val1;
	@NotBlank
	private String val2;
}

コントローラでバリデーション適用

コントローラの引数にアノテーション @Validated とバリデーション結果をとれる BindingResult を追加する
引数の順番は必ず @Validated つけたやつの後に BindingResult にする
この順番以外だとエラーになるので注意!

簡単な使用例
	@PostMapping("/url_samp")
	public String sample(Model model, @Validated @ModelAttribute XxxDto dto, BindingResult result) {
        // バリデーション確認
        if (result.hasErrors()) {
            // とりあえずエラー内容出力
            result.getFieldErrors().forEach(e -> System.out.println(e.getField() + ":" + e.getDefaultMessage()));
            // 結果を画面に設定
            model.addAttribute("errorResult", result);
            return "sampl";
        }
        // バリデーションOKの時の処理
        // ・
        // ・
        return "sampl";
    }

html でエラー内容表示

一旦、簡易にバリデーション結果から直接、エラー項目とメッセージを取得して表示

簡単な使用例
		<div th:if="${errorResult}">
			<li th:each="err : ${errorResult.fieldErrors}" th:text="${err.field + ':' + err.defaultMessage}"></li>
		</div>

メッセージを変える

メッセージプロパティの元は hibernate-validator に置いてある
上書きだったり新しいバリデータ作るときは resources の直下に以下のファイルを作る
上書きのときは元々のキーと合わせる必要あり

  • ValidationMessages.properties
  • ValidationMessages_ja.properties
簡単な例 ValidationMessages_ja.properties
jakarta.validation.constraints.NotBlank.message        = ないよ。。。blank
jakarta.validation.constraints.NotNull.message         = ないよ。。。null

独自でバリデーションつくる

標準にはない独自バリデーションが作れる、DBへのチェックなども作れる
クラスは以下の2つを作る
使いたいときは作ったアノテーションクラスをクラス or クラス変数 or 引数に追加するだけであとは標準と同じ!

  • アノテーションクラス(クラス、クラス変数、引数につけるアノテーション)
  • バリデーションクラス(チェック行うクラス)

あとメッセージの追加を忘れずに

  • ValidationMessages.properties
  • ValidationMessages_ja.properties
アノテーションクラス SampleValue
package com.example.demo.validator;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;

// バリデーションクラスを設定
@Constraint(validatedBy = SampleValueValidator.class)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,  ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleValue {
    // メッセージプロパティに設定するキーを使う
	String message() default "{sample.value.message}";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};
}
バリデーションクラス SampleValueValidator
package com.example.demo.validator;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

// ConstraintValidator<アノテーションクラス設定, バリデーションする型設定> の実態クラスにする
public class SampleValueValidator implements ConstraintValidator<SampleValue, String> {

    // バリデーションの実装, バリデーションエラーの時は false を返す
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return "Sample".equals(value);
    }
}
ValidationMessages.properties
sample.value.message = Let's make it Sample
ValidationMessages_ja.properties
sample.value.message = Sample にしましょう

バリデーションの実行制御(コントローラごとに分けるパターン)

入力フォームで使うオブジェクトのクラス変数に追加したバリデーションでアクションごとに実行制御できる
実行制御するときはアノテーションクラスの groups を使う
入力フォームで使うオブジェクトのクラス変数のアノテーションのところに groups={ クラス... } を設定
コントローラの引数のアノテーションのところに @Validated({ クラス... }) を設定
クラスを合わせる必要がある(クラス自体は作っても良いし、すでにあるやつでもOK、アクションを制御できる感じのやつを使う)

簡単な使用例 入力フォームで使うオブジェクト
@Data
@AllArgsConstructor
@NoArgsConstructor
public class XxxDto {
    // groups = { クラス... } ここに設定したクラスをコントローラ側で設定するとバリデーション実行
	@NotNull(groups = { ClasA.class })
	private Integer val1;
	@NotBlank
	private String val2;
}
簡単な使用例 コントローラ
    // Validated({クラス...}) 上のオブジェクトで設定したクラスを設定
    // Default.class を設定しておくと groups の設定がないバリデーションも実行できる
    // Validated でクラスを設定しない時は Default.class を設定してることになる
	@PostMapping("/url_samp")
	public String sample(Model model, @Validated({ Default.class, ClasA.class }) @ModelAttribute XxxDto dto, BindingResult result) {
        // バリデーション確認
        if (result.hasErrors()) {
            // とりあえずエラー内容出力
            result.getFieldErrors().forEach(e -> System.out.println(e.getField() + ":" + e.getDefaultMessage()));
            // 結果を画面に設定
            model.addAttribute("errorResult", result);
            return "sampl";
        }
        // バリデーションOKの時の処理
        // ・
        // ・
        return "sampl";
    }
0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0