【问题标题】:How to apply custom validation on a field using javax validation only if it is not null?仅当字段不为空时,如何使用 javax 验证对字段应用自定义验证?
【发布时间】:2020-07-26 14:18:52
【问题描述】:

我正在开发 Spring Boot 应用程序中的 javax 验证 API。我有一个用户 bean,我必须验证请求中给出的用户名是唯一的,并且不存在于数据库中。

我为此要求创建了自定义注释 (UniqueUser.java) 和自定义验证器(UniqueUserValidator.java)。

public class User  {
    @NotNull
    @UniqueUser
    private String username;

    @NotNull
    private String password;

    @NotNull
    @Email
    private String email;

    @NotNull
    private String phone;
}

UniqueUser.java

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueUserValidator.class)
@Documented
public @interface NameMatch
{
    String message() default "User id already exists";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

UniqueUserValidator.java

public class UniqueUserValidator implements ConstraintValidator<NameMatch, Object>
{
    @Autowired
    UserRepository userRepository;
   
    @Override
    public boolean isValid(String userName, final ConstraintValidatorContext context)
    {
        boolean isValidUser = false;
        if(userName!=null && !userName.isEmpty()) {
        Optional<User> user= userRepository.findByUserId(userName);
           isValidUser = !user.isPresent(); 
        }
        return isValidUser;
    }
}

在上面的代码中,即使用户名字段为空并显示用户名已存在错误消息,也会为用户名字段调用唯一用户验证。我希望仅当用户名具有某些值时才调用自定义验证器。是否可以避免此调用。

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

public class UniqueUserValidator implements ConstraintValidator<NameMatch, Object>
{
    @Autowired
    UserRepository userRepository;
   
    @Override
    public boolean isValid(String userName, final ConstraintValidatorContext context)
    {
        boolean isValidUser = false;
        if(userName!=null && !userName.isEmpty()) {
        Optional<User> user= userRepository.findByUserId(userName);
           isValidUser = !user.isPresent(); 
        } else {
           isValidUser = true; 
        }
        return isValidUser;
    }
} 

【问题讨论】:

  • 你是说你不想打电话给if(userName!=null &amp;&amp; !userName.isEmpty())
  • 如果您不签入isValid,那么您必须在某处检查 null 以做出决定,那么实际上没有任何优化。您当前的实现很好
  • 而是使用我喜欢使用的自定义注释在服务内部进行此检查,因为您在控制器之前调用存储库,这根本不是一个好的模式,恕我直言。
  • 附注:我认为您的意思是 public @interface UniqueUser,因为您在 DTO 中使用 @UniqueUser

标签: java spring-boot validation hibernate-validator


【解决方案1】:

我想你要找的是Grouping constraints

组允许您限制在期间应用的一组约束 验证。验证组的一个用例是 UI 向导,其中 每个步骤只有一个指定的约束子集应该得到验证。 目标组作为 var-arg 参数传递给 合适的验证方法。

在您的情况下,它应该如下所示:

@GroupSequence({ FirstConstaint.class, SecondConstaint.class })
public class User  {
    @NotNull(groups = FirstConstaint.class)
    @UniqueUser(groups = SecondConstaint.class)
    private String username;

    // the rest of your fields
}

interface FirstConstaint {
}

interface SecondConstaint {
}

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

否则就像@User说你可以在服务层使用这个检查^^

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多