9
7

More than 3 years have passed since last update.

Spring Boot 自作アノテーションを作成して複数項目にvalidationをかける

Posted at

やりたいこと

リクエストクラスでは以下@NotNull@Sizeのような
@のついたアノテーションで入力チェックをすることができる。
用意されているアノテーションは一つの項目のみしかチェックを行うことができない。
複数の項目を検証するアノテーションが欲しいため、独自に作成したアノテーションで入力チェックを行いたい。

リクエストクラス

public class SampleRequest {

  // nullは不可
  @NotNull
  private Integer id;

  // 1〜50文字
  @Size(min = 1, max = 50)
  private String name;

  private String name1;

  private String name2;

  private String name3;

  public Sample convert() {
    Sample sample = new Sample();
    sample.setId(id);
    sample.setName(name);
    sample.setName(name1);
    sample.setName(name2);
    sample.setName(name3);
    return sample;
  }

}

今回やること

上記のリクエストクラスで、「name1, name2, name3のうち2つ以上の入力が必要」
という入力チェックを行うアノテーションを作成する。

1. 入力チェック内容を記載したクラスを作る

どんな入力チェックを行いたいかを記載する。


package test.pj.web.validation;

import java.util.ArrayList;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

// ConstraintValidator の実装クラスとして作成する
// <>内の引数1つ目は下記2のアノテーションクラス名
public class SampleAnnotationValidation
    implements ConstraintValidator<SampleAnnotation, Object> {

  // バリデーション対象の変数の値を入れる
  private String[] fields;
  // アノテーションクラス(下記2)で設定しているエラーメッセージが入る
  private String message;

  /**
   * 初期化処理 
   * ()内のクラスは下記2のアノテーションクラス
   */
  public void initialize(SampleAnnotation annotation) {
    this.fields = annotation.fields();
    this.message = annotation.message();
  }

  /**
   *  自分でバリデーション内容を設定する
   */
  @Override
  public boolean isValid(Object value, ConstraintValidatorContext context) {

    BeanWrapper beanWrapper = new BeanWrapperImpl(value);

    // 入力されている回数をカウントする変数を作成
    Integer idCount = 0;

    for (String string : fields) {
      // 以下で、fieldValueに、validation対象の各値(今回の場合、name1, name2, name3)が入る
      Object value = beanWrapper.getPropertyValue(string);

      // 入力がある場合、入力カウントに1を足しておく
      if (value != "") {
        idCount += 1;
      }
    }

    // 入力数が2以上のときはtrueを返す
    if (idCount >= 2)) {
      return true;
    }

    // それ以外はfalseを返し、messageを出す
    context.disableDefaultConstraintViolation();
    context.buildConstraintViolationWithTemplate(message).addPropertyNode(fields[0])
        .addConstraintViolation();
    return false;
  }

}

2. アノテーションクラスを作る

@hogehogeの名前の部分を作る


package test.pj.web.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
// 1で記載した入力チェック内容を記載したクラスをかく
@Constraint(validatedBy = {SampleAnnotationValidation.class})
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
// クラス名には、アノテーション名として使いたい名前をつける
public @interface SampleAnnotation {

  // 入力チェック不可だった場合に、表示するエラーメッセージ
  String message() default "name1, name2, name3のいずれか2つ以上を入力してください。";

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

  Class<? extends Payload>[] payload() default {};

  @Target({ElementType.TYPE})
  @Retention(RetentionPolicy.RUNTIME)
  @Documented
  public @interface List {
    SampleAnnotation[] value();
  }

  // チェックする値を格納
  String[] fields();

}

3.リクエストクラスに自作したアノテーションをつける

package test.pj.web.validation;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import test.pj.web.validation.SampleAnnotation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
// 2で作成したアノテーション名と、入力チェックを行いたい項目を入れる
@SampleAnnotation(fields = {"name1", "name2", "name3"})
@AllArgsConstructor
@NoArgsConstructor
public class SampleRequest {

  // nullは不可
  @NotNull
  private Integer id;

  // blankは不可、1〜50文字
  @NotBlank
  @Size(min = 1, max = 50)
  private String name;

  private String name1;

  private String name2;

  private String name3;

  public Sample convert() {
    Sample sample = new Sample();
    sample.setId(id);
    sample.setName(name);
    sample.setName(name1);
    sample.setName(name2);
    sample.setName(name3);
    return sample;
  }

}
9
7
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
9
7