38

initBinderメソッドを使用してユーザーバリデーターを追加しています:

@InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new UserValidator());
    }

こちらがUserValidator

public class UserValidator implements Validator {

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

    public void validate(Object target, Errors errors) {
        User u = (User) target;

        // more code here
    }
}

コントローラーメソッドのvalidate呼び出し中に、メソッドが適切に呼び出されています。

@RequestMapping(value = "/makePayment", method = RequestMethod.POST)
public String saveUserInformation(@Valid User user, BindingResult result, Model model){

    // saving User here

    // Preparing CustomerPayment object for the payment page.
    CustomerPayment customerPayment = new CustomerPayment();
    customerPayment.setPackageTb(packageTb);
    model.addAttribute(customerPayment);
    logger.debug("Redirecting to Payment page.");

    return "registration/payment";
}

しかし、支払い画面に戻ると、次のエラーが表示されます。

java.lang.IllegalStateException: Validator [com.validator.UserValidator@710db357] の無効なターゲット: com.domain.CustomerPayment[ customerPaymentId=null ] org.springframework.validation.DataBinder.setValidator(DataBinder.java:476) com.web. UserRegistrationController.initBinder(UserRegistrationController.java:43) sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブメソッド) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java .lang.reflect.Method.invoke(Method.java:597) org.springframework.web.bind.annotation.support.HandlerMethodInvoker.initBinder(HandlerMethodInvoker.java:393) org.springframework.web.bind.annotation.support.HandlerMethodInvoker .updateModelAttributes(HandlerMethodInvoker.java:222) org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:429) org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java: 414)

これは、 a を返しているのに、そのためにCustomerPayment定義されたバリデータがないことが原因である可能性があります。

メソッドに複数のバリデーターを追加することもできませんinitBinder

どうすればこれを修正できますか?

4

9 に答える 9

107

@InitBinderアノテーションの値を、検証するコマンドの名前に設定する必要があります。これにより、Spring にバインダーを適用する対象が伝えられます。それがなければ、Spring はそれをすべてに適用しようとします。これが、その例外が表示される理由です。Spring はUserValidator、タイプ のパラメーターにバインダーを適用しようとしていますCustomerPayment

あなたの特定のケースでは、次のようなものが必要なようです:

@InitBinder("user")
protected void initBinder(WebDataBinder binder) {
    binder.setValidator(new UserValidator());
}

2 番目の質問に対して、Rigg802 が説明したように、Spring は単一のコマンドに複数のバリデーターをアタッチすることをサポートしていません。@InitBinderただし、さまざまなコマンドに対して複数のメソッドを定義できます。したがって、たとえば、以下を 1 つのコントローラーに配置して、ユーザーと支払いのパラメーターを検証できます。

@InitBinder("user")
protected void initUserBinder(WebDataBinder binder) {
    binder.setValidator(new UserValidator());
}

@InitBinder("payment")
protected void initPaymentBinder(WebDataBinder binder) {
    binder.setValidator(new CustomerPaymentValidator());
}
于 2013-04-03T19:40:28.560 に答える
8

1 つのコントローラーには 1 つのコマンド オブジェクトに対して 1 つのバリデーターしかありません。すべてのバリデータを取得して個別に実行する「複合バリデータ」を作成する必要があります。

これを行う方法を説明するチュートリアルは次のとおりです:複数のバリデータを使用する

于 2013-01-26T11:40:50.460 に答える
6

@ Rigg802 で説明されている CompoundValidator のようなものを使用することを強制する、デフォルトで現在のエンティティに適用できないすべてのバリデーターを Spring が除外しない理由がわかりません。

InitBinderカスタムバリデーターを適用する方法とタイミングを完全に制御することはできませんが、名前のみを指定できます。私の観点からは、これは十分ではありません。

他にできることは、自分でチェックを実行し、実際に必要な場合にのみバリデーターをバインダーに追加することです。これは、バインダー自体がバインディング コンテキスト情報を持っているためです。

たとえば、組み込みのバリデーターに加えて、ユーザー オブジェクトで動作する新しいバリデーターを追加する場合は、次のように記述できます。

@InitBinder
protected void initBinder(WebDataBinder binder) {
  Optional.ofNullable(binder.getTarget())
      .filter((notNullBinder) -> User.class.equals(notNullBinder.getClass()))
      .ifPresent(o -> binder.addValidators(new UserValidator()));

}

于 2015-11-04T16:16:05.250 に答える
6

ApplicationContext ですべての org.springframework.validation.Validator を反復処理し、リクエストごとに @InitBinder で適切なものをセットアップすることで、複数のバリデーターを追加できます。

@InitBinder
public void setUpValidators(WebDataBinder webDataBinder) {
    for (Validator validator : validators) {
        if (validator.supports(webDataBinder.getTarget().getClass())
                && !validator.getClass().getName().contains("org.springframework"))
            webDataBinder.addValidators(validator);
    }
}

例と簡単なベンチマークについては、私のプロジェクトを参照してください。https://github.com/LyashenkoGS/spring-mvc-and-jms-validation-POC/tree/benchamark

于 2017-06-14T09:14:53.837 に答える
3

単純なハックがあり、常にメソッドで戻りtruesupportsクラス チェックを にデリゲートしvalidateます。次に、基本的に、複数のバリデータを問題なく追加できますinitBinder

@Component
public class MerchantRegisterValidator implements Validator {

    @Autowired
    private MerchantUserService merchantUserService;

    @Autowired
    private MerchantCompanyService merchantCompanyService;

    @Override
    public boolean supports(Class<?> clazz) {
        return true; // always true
    }

    @Override
    public void validate(Object target, Errors errors) {

        if (!RegisterForm.getClass().equals(target.getClass()))
            return; // do checking here.

        RegisterForm registerForm = (RegisterForm) target;

        MerchantUser merchantUser = merchantUserService.getUserByEmail(registerForm.getUserEmail());

        if (merchantUser != null) {
            errors.reject("xxx");
        }

        MerchantCompany merchantCompany = merchantCompanyService.getByRegno(registerForm.getRegno());

        if (merchantCompany != null) {
            errors.reject("xxx");
        }

    }

}
于 2018-01-22T04:21:21.407 に答える
2

Spring MVC 4.x では、1 つのコマンドで複数のバリデーターがサポートされるようになりました。次のスニペット コードを使用できます。

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.addValidators(new UserValidator(), new CustomerPaymentValidator());
}
于 2014-01-26T07:13:40.810 に答える
-3

リクエストを次のように宣言します

(... , Model model,HttpServletRequest request)

変更する

model.addAttribute(customerPayment);

request.setAttribute("customerPayment",customerPayment);
于 2014-04-01T17:26:29.043 に答える