如何在使用javax验证时,仅当字段不为null时对其应用自定义验证?

huangapple go评论97阅读模式
英文:

How to apply custom validation on a field using javax validation only if it is not null?

问题

我正在Spring Boot应用程序中使用javax验证API。我有一个用户实体(bean),我需要验证请求中提供的用户名是否唯一且不存在于数据库中。

我已经为此创建了自定义注解(UniqueUser.java)和自定义验证器(UniqueUserValidator.java)。

  1. public class User {
  2. @NotNull
  3. @UniqueUser
  4. private String username;
  5. @NotNull
  6. private String password;
  7. @NotNull
  8. @Email
  9. private String email;
  10. @NotNull
  11. private String phone;
  12. }

UniqueUser.java

  1. @Target({TYPE, ANNOTATION_TYPE})
  2. @Retention(RUNTIME)
  3. @Constraint(validatedBy = UniqueUserValidator.class)
  4. @Documented
  5. public @interface UniqueUser {
  6. String message() default "User id already exists";
  7. Class<?>[] groups() default {};
  8. Class<? extends Payload>[] payload() default {};
  9. }

UniqueUserValidator.java

  1. public class UniqueUserValidator implements ConstraintValidator<UniqueUser, Object> {
  2. @Autowired
  3. UserRepository userRepository;
  4. @Override
  5. public boolean isValid(String userName, final ConstraintValidatorContext context) {
  6. boolean isValidUser = false;
  7. if (userName != null && !userName.isEmpty()) {
  8. Optional<User> user = userRepository.findByUserId(userName);
  9. isValidUser = !user.isPresent();
  10. }
  11. return isValidUser;
  12. }
  13. }

在上述代码中,即使用户名字段为null,唯一用户验证也会被调用,并显示“用户名已存在”错误消息。我希望只有在用户名具有某些值时才调用自定义验证器。是否有可能避免这种调用。

我可以通过修改下面的方法来修复错误,如果用户名为null,则返回true,但我想避免这种不必要的调用。

  1. public class UniqueUserValidator implements ConstraintValidator<UniqueUser, Object> {
  2. @Autowired
  3. UserRepository userRepository;
  4. @Override
  5. public boolean isValid(String userName, final ConstraintValidatorContext context) {
  6. boolean isValidUser = false;
  7. if (userName != null && !userName.isEmpty()) {
  8. Optional<User> user = userRepository.findByUserId(userName);
  9. isValidUser = !user.isPresent();
  10. } else {
  11. isValidUser = true;
  12. }
  13. return isValidUser;
  14. }
  15. }
英文:

I am working on javax validation API in Spring Boot Application. I have a User bean and i have to validate that username given in request is unique and doesn't exist into Database.

I have created custom annotation (UniqueUser.java) and custom Validator(UniqueUserValidator.java) for this requirement.

  1. public class User {
  2. @NotNull
  3. @UniqueUser
  4. private String username;
  5. @NotNull
  6. private String password;
  7. @NotNull
  8. @Email
  9. private String email;
  10. @NotNull
  11. private String phone;
  12. }

UniqueUser.java

  1. @Target({TYPE, ANNOTATION_TYPE})
  2. @Retention(RUNTIME)
  3. @Constraint(validatedBy = UniqueUserValidator.class)
  4. @Documented
  5. public @interface NameMatch
  6. {
  7. String message() default &quot;User id already exists&quot;;
  8. Class&lt;?&gt;[] groups() default {};
  9. Class&lt;? extends Payload&gt;[] payload() default {};
  10. }

UniqueUserValidator.java

  1. public class UniqueUserValidator implements ConstraintValidator&lt;NameMatch, Object&gt;
  2. {
  3. @Autowired
  4. UserRepository userRepository;
  5. @Override
  6. public boolean isValid(String userName, final ConstraintValidatorContext context)
  7. {
  8. boolean isValidUser = false;
  9. if(userName!=null &amp;&amp; !userName.isEmpty()) {
  10. Optional&lt;User&gt; user= userRepository.findByUserId(userName);
  11. isValidUser = !user.isPresent();
  12. }
  13. return isValidUser;
  14. }
  15. }

In above code, the unique user validation get called for username field even if the field is null and shows Username already exists error message. I want the custom validator to get called only when username has some value. Is it possible to avoid this call.

I can fix the error by modifying the below method and returning true if username is null, but i want't to avoid this unnecessary call.

  1. public class UniqueUserValidator implements ConstraintValidator&lt;NameMatch, Object&gt;
  2. {
  3. @Autowired
  4. UserRepository userRepository;
  5. @Override
  6. public boolean isValid(String userName, final ConstraintValidatorContext context)
  7. {
  8. boolean isValidUser = false;
  9. if(userName!=null &amp;&amp; !userName.isEmpty()) {
  10. Optional&lt;User&gt; user= userRepository.findByUserId(userName);
  11. isValidUser = !user.isPresent();
  12. } else {
  13. isValidUser = true;
  14. }
  15. return isValidUser;
  16. }
  17. }

答案1

得分: 1

我认为您要寻找的是分组约束

> 分组允许您在验证期间限制应用的约束集。验证组的一个用例是 UI 向导,在每个步骤中只需要验证指定的一部分约束。目标组以 var-arg 参数的形式传递给适当的验证方法。

在您的情况下,应该是这样的:

  1. @GroupSequence({ FirstConstaint.class, SecondConstaint.class })
  2. public class User {
  3. @NotNull(groups = FirstConstaint.class)
  4. @UniqueUser(groups = SecondConstaint.class)
  5. private String username;
  6. // 其他字段
  7. }
  8. interface FirstConstaint {
  9. }
  10. interface SecondConstaint {
  11. }

这样,它只会在字段不为空时检查 @UniqueUser,否则,它将返回 @NotNull 验证的消息。

另外,如 @User 所说,您还可以将这些检查用于服务层 ^^

英文:

I think what you are looking for is Grouping constraints;

> Groups allow you to restrict the set of constraints applied during
> validation. One use case for validation groups are UI wizards where in
> each step only a specified subset of constraints should get validated.
> The groups targeted are passed as var-arg parameters to the
> appropriate validate method.

In your case it should look like this:

  1. @GroupSequence({ FirstConstaint.class, SecondConstaint.class })
  2. public class User {
  3. @NotNull(groups = FirstConstaint.class)
  4. @UniqueUser(groups = SecondConstaint.class)
  5. private String username;
  6. // the rest of your fields
  7. }
  8. interface FirstConstaint {
  9. }
  10. interface SecondConstaint {
  11. }

This way, it will check @UniqueUser only if the field is not null, otherwise, it will return the message of @NotNull validation.

Otherwise like @User said you can use this checks in service layer ^^

huangapple
  • 本文由 发表于 2020年7月26日 22:18:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/63101373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定