web-dev-qa-db-ja.com

Spring MVCバリデーターアノテーション+カスタム検証

私は、Spring MVCバリデータに基づいて検証を行う必要がある、Spring MVCアプリケーションに取り組んでいます。そのための最初のステップとして、クラスとセットアップコントローラーに注釈を追加しましたが、正常に機能します。そして今、複雑なロジックを実行するためにカスタムバリデータを実装する必要がありますが、既存のアノテーションを使用して、追加のチェックを追加したいだけです。

My Userクラス:

public class User
{
    @NotEmpty
    private String name;

    @NotEmpty
    private String login; // should be unique
}

私のバリデーター:

@Component
public class UserValidator implements Validator
{

    @Autowired
    private UserDAO userDAO;

    @Override
    public boolean supports(Class<?> clazz)
    {
        return User.class.equals(clazz) || UsersForm.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors)
    {
        /*
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "NotEmpty.user");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "login", "NotEmpty.user");
        */
        User user = (User) target;
        if (userDAO.getUserByLogin(user.getLogin()) != null) {
            errors.rejectValue("login", "NonUniq.user");
        }
    }
}

私のコントローラー:

@Controller
public class UserController
{
    @Autowired
    private UserValidator validator;

    @InitBinder
    protected void initBinder(final WebDataBinder binder)
    {
        binder.setValidator(validator);
    }

    @RequestMapping(value = "/save")
    public ModelAndView save(@Valid @ModelAttribute("user") final User user,
            BindingResult result) throws Exception
    {
        if (result.hasErrors())
        {
            // handle error
        } else
        {
            //save user
        }
    }
}

だから、カスタムバリデータと注釈を一緒に使用することは可能ですか?そして、もしそうならどうですか?

31
Vartlok

これは一種の古い質問ですが、グーグルにとっては...

addValidatorsの代わりにsetValidatorを使用する必要があります。次のように:

@InitBinder
protected void initBinder(final WebDataBinder binder) {
    binder.addValidators(yourCustomValidator, anotherValidatorOfYours);
}

PS:addValidatorsは複数のパラメーターを受け入れます(省略記号)

org.springframework.validation.DataBinderのソースをチェックアウトすると、以下が表示されます。

public class DataBinder implements PropertyEditorRegistry, TypeConverter {

    ....

    public void setValidator(Validator validator) {
        assertValidators(validator);
        this.validators.clear();
        this.validators.add(validator);
    }

    public void addValidators(Validator... validators) {
        assertValidators(validators);
        this.validators.addAll(Arrays.asList(validators));
    }

    ....

}

ご覧のとおり、setValidatorは既存の(デフォルトの)バリデータをクリアするため、@Validアノテーションは期待どおりに機能しません。

58
destan

問題を正しく理解している場合、カスタムバリデータを使用するとすぐに、@NotEmpty注釈は発生しなくなりました。これは、springを使用する場合に一般的です。デフォルトで指定された機能をオーバーライドする場合、明示的に呼び出す必要があります。

LocalValidatorFactoryBeanを生成し、メッセージソース(存在する場合)を挿入する必要があります。次に、その基本的なバリデータをカスタムバリデータに挿入し、注釈の検証をそれに委任します。

Java設定を使用すると、次のようになります。

@Configuration
public class ValidatorConfig {
    @Autowired
    private MessageSource messageSource;

    @Bean
    public Validator basicValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator;
    }
}

次に、UserValidatorを変更して使用します。

@Component
public class UserValidator implements Validator
{

    @Autowired
    @Qualifier("basicValidator")
    private Validator basicValidator;

    @Autowired
    private UserDAO userDAO;

    // ...

    @Override
    public void validate(Object target, Errors errors)
    {
        basicValidator.validate(target, errors);
        // eventually stop if any errors
        //  if (errors.hasErrors()) { return; }
        User user = (User) target;
        if (userDAO.getUserByLogin(user.getLogin()) != null) {
            errors.rejectValue("login", "NonUniq.user");
        }
    }
}
9
Serge Ballesta

まあ私にとっては、削除する必要があります

 @InitBinder
protected void initBinder(final WebDataBinder binder)
{
    binder.setValidator(validator);
}

出て

@Valid @ModelAttribute("user") final User user,
        BindingResult result

そして関数makeの後

validator.validate(user,result)

このように、@ Validで基本的な検証を使用し、配置した後、より複雑な検証を行います。

InitBinderを使用すると、複雑なロジックを使用して検証を設定し、基本的なロジックを設定できるためです。

多分間違っている、私は常にバリデータなしで@Validを使用しています。

7
nicearma