1. ホーム
  2. java

[解決済み] Spring MVC:バリデーションを行うには?

2022-04-25 19:54:49

質問

ユーザー入力のフォームバリデーションを行うための、最もクリーンで最良の方法を知りたいです。いくつかの開発者が org.springframework.validation.Validator . それについて質問です。私はそれがクラスを検証するのを見ました。このクラスは、ユーザー入力の値を手動で埋めて、バリデータに渡す必要があるのでしょうか?

ユーザー入力を検証するための最もクリーンで最良の方法について迷っています。従来の方法である request.getParameter() を手動でチェックし、さらに nulls の中ですべての検証を行いたくないのですが。 Controller . この辺りについて、何か良いアドバイスがあれば、とてもありがたいです。私はこのアプリケーションでHibernateを使用していません。

解決方法は?

Spring MVCでは、アノテーションを使用する方法、手動で行う方法、または両方を混ぜる方法の3種類のバリデーションがあります。しかし、あなたのプロジェクト、問題、コンテキストに合った方法があるはずです。

ユーザーを作ろう :

public class User {

    private String name;

    ...

}

方法1. Spring 3.x+で、簡単な検証を行う場合は、以下のようにします。 javax.validation.constraints アノテーション(JSR-303アノテーションとも呼ばれる)を使用します。

public class User {

    @NotNull
    private String name;

    ...

}

のように、ライブラリにJSR-303プロバイダが必要です。 Hibernate Validator このライブラリはデータベースやリレーショナルマッピングとは関係なく、単にバリデーションを行うだけです:-)。

そして、コントローラには、次のようなものがあります。

@RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, @Valid @ModelAttribute("user") User user, BindingResult result){
    if (result.hasErrors()){
      // do something
    }
    else {
      // do something else
    }
}

Valid に注目してください。もしユーザーの名前が NULL だった場合、result.hasErrors() は true になります。

方法2. 複雑な検証を行う場合(大きなビジネス検証ロジック、複数のフィールドにまたがる条件付き検証など)、または何らかの理由で方法1を使用できない場合は、手動検証を使用します。コントローラのコードとバリデーションロジックを分離するのはよい習慣です。バリデーションクラスをゼロから作成するのではなく、Springが提供する便利な org.springframework.validation.Validator インターフェイスを使用します(Spring 2以降)。

では、次のようなものがあるとしよう。

public class User {

    private String name;

    private Integer birthYear;
    private User responsibleUser;
    ...

}

のような複雑なバリデーションを行いたい場合、ユーザーの年齢が18歳未満の場合、responsibleUserはnullであってはならず、responsibleUserの年齢が21歳以上でなければならない、というものです。

次のようなことをすることになります。

public class UserValidator implements Validator {

    @Override
    public boolean supports(Class clazz) {
      return User.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
      User user = (User) target;

      if(user.getName() == null) {
          errors.rejectValue("name", "your_error_code");
      }

      // do "complex" validation here

    }

}

そして、コントローラの中に:

@RequestMapping(value="/user", method=RequestMethod.POST)
    public createUser(Model model, @ModelAttribute("user") User user, BindingResult result){
        UserValidator userValidator = new UserValidator();
        userValidator.validate(user, result);

        if (result.hasErrors()){
          // do something
        }
        else {
          // do something else
        }
}

バリデーションエラーがある場合、result.hasErrors()はtrueになります。

注意: コントローラの @InitBinder メソッドで、 "binder.setValidator(...)" のようにバリデータを設定することもできます (この場合、デフォルトバリデータを置き換えるので、メソッド 1 と 2 を混用することはできません)。あるいは、コントローラのデフォルトコンストラクタでこれをインスタンス化します。ほとんどのバリデータはシングルトンであり、ユニットテストのモックが容易になり、バリデータは他のSpringコンポーネントを呼び出すことができるため、非常に便利です。

方法3. 両方の方法を組み合わせて使ってはどうでしょうか。name"属性のような単純なものは、アノテーションで検証します(素早くできて、簡潔で読みやすいのです)。重い検証はバリデータに任せる(複雑な検証用アノテーションをカスタマイズするのに何時間もかかる場合、あるいはアノテーションを使うのが不可能な場合)。私は以前のプロジェクトでこれを行いましたが、それは魅力的なように機能し、素早く&簡単になりました。

警告 : 間違えてはいけないのは バリデーション処理 に対して 例外処理 . この記事を読む を使用するタイミングを知ることができます。

参考文献 :