SpringBootでリクエストパラメーターをBeanValidationでバリデーションする方法

技術

はじめに

こんにちは!さいけです。

本記事は、「SpringBootでリクエストパラメーターをBeanValidationでバリデーションする方法」について紹介します。

前提

前提として、本記事では複雑または発展的な内容は含みません。

また、BeanValidationの深い仕組みの解説までは行いません。

SpringBootでリクエストパラメーターをBeanValidationでバリデーションする方法

以下の実装サンプルクラスを例に、追って解説していきます。

  • ValidateService
  • CreateErrorMessageService
  • Controller
  • Entity

ValidateService

バリデーションを実行するサービスクラスです。

@Service  
public class ValidateService {

    public <T> Set<ConstraintViolation<T>> validate(T target) {

        // Validatorを作成する
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        // バリデーションを実行し、その結果を返す
        return validator.validate(target);
    }
}

解説

  • validateメソッドはオブジェクトを引数として受け取れます。また、オブジェクトを可変で受け取れるようにジェネリクスで定義しています。
  • 次にバリデーションが行えるようにvalidator変数にバリデーションの関数を格納します。
  • さいごに、targetを引数にバリデーションを実行し、結果を返却します。

CreateErrorMessageService

バリデーションエラーを作成するサービスクラスです。

@Service
public class CreateErrorMessageService {

    public <T> String createErrorMessage(
            Set<ConstraintViolation<T>> constraintViolations) {

        List<String> errorMessageList = new ArrayList<>();

        for (ConstraintViolation<T> violation : constraintViolations) {
            errorMessageList.add(violation.getMessage());
        }

        return String.join(",", errorMessageList);
    }
}

解説

  • CreateErrorMessageServiceはSet<ConstraintViolation<T>>型の変数を引数として受け取ることができます。
  • Set<ConstraintViolation<T>>の変数には、バリデーションによって精査されたものが格納されています。
  • エラーメッセージを格納する箱として、List型のerrorMessageListを用意します。
  • 引数のconstraintViolationsをforループし、小要素のメッセージを取り出し、errorMessageListに格納していきます。
  • さいごに、メッセージが格納されたリストの小要素を,繋ぎをして文字列で返却します。

Controller

リクエストパラメーターを受け取り、バリデーションを処理後、結果を返却するControllerクラスです。

@RestController
@RequiredArgsConstructor
public class BeanValidationController {

    private final ValidateService validateService;
    private final CreateErrorMessageService createErrorMessageService;

    @GetMapping(value = "/beanvalidation")
    public String getPerson(
            @RequestParam("name") String name,
            @RequestParam("age") Integer age) {

        // オブジェクトを生成
        PersonEntity personEntity = new PersonEntity(name, age);

        // バリデーションした結果を保持する
        Set<ConstraintViolation<PersonEntity>> validatedPersonEntity = validateService.validate(personEntity);

        // バリデーションに引っかかったものがあれば、そのエラーメッセージを作成して返す
        if (validatedPersonEntity.size() > 0) {
            return createErrorMessageService.createErrorMessage(validatedPersonEntity);
        }

        return "私の名前は" + name + "です。年齢は" + age + "です。";
    }
}

解説

  • getPersonメソッドはリクエストパラメーターのnameとageを引数に受け取れます。
  • 先程作ったバリデーションクラスの引数は、オブジェクトを期待しているため、あらかじめリクエストパラメーターで受け取った引数をオブジェクトに変換します。
  • validateService.validateにオブジェクトを引数として渡して、結果をvalidatedPersonEntity変数に保持します。
  • バリデーションに引っかかったものがあれば、validatedPersonEntityに何かしら格納されるので、ifでvalidatedPersonEntityのサイズを確認します。
  • validatedPersonEntityが1より大きければ、createErrorMessageService.createErrorMessageにvalidatedPersonEntityを渡します。
  • 何も格納されていなければ、バリデーションには引っかからなかったということなので、そのままリクエストパラメーターで受け取った値を整形して、文字列で返します。

 

Entity

各値を保持するEntityクラスです。

@Getter
@AllArgsConstructor
public class PersonEntity {

    @NotBlank
    private String name;

    @NotNull
    private Integer age;
}

解説

  • それぞれのパラメーターにBeanValidationアノテーションで条件をつけている

実行結果

正常なケース

リクエストパラメーターが不備がなく、正常なケースです。

バリデーションエラーメッセージは返却されていません。

バリデーションエラーに引っかかるケース:片方のパラメーターが空

次に、バリデーションに引っかかるケースで試します。

ageを空にしてリクエストします。

ageに不備があったので、「must not be null」と返却されました。

バリデーションエラーに引っかかるケース:両方のパラメーターが空

さらに、nameも空にしてリクエストしてみます。


ageに加え、nameにも不備があったので、それぞれに対応するバリデーションエラー文言が返却されました。

おわりに

今回は、「SpringBootでリクエストパラメーターをBeanValidationでバリデーションする方法」を紹介しました。

BeanValidationでバリデーションするのは色々準備しなきゃいけなくて少し大変です。

しかし、BeanValidationでバリデーションさせるのは、状況によってはとても有用です。

柔軟な使い方が色々できるので、ぜひ参考にして使ってみてください。

 

コメント

タイトルとURLをコピーしました