验证字段时如何避免重复检查空值?

时间:2019-06-09 17:53:26

标签: java validation nullpointerexception

我想使用Java验证程序来验证简单的帐户数据。帐户数据字段都不能为空,因此所有注释都为@NotNull。但是我仍然必须检查提供的密码及其重复次数是否相等。这迫使我通过检查null相等性来避免NullPointerException。请查看代码(为简洁起见,我省略了Maven依赖,因为依赖关系和正确的库不会引起问题):

AccountData类:

@ValidPassword
class AccountData {

@NotNull
public String login;

@NotNull
public String password;

@NotNull
public String repeatedPassword;

@NotNull
public String emailAddress;

@NotNull
public String countryName;  
}

ValidCountry接口:

@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CountryValidatorImplementation.class)
@Documented
@interface ValidPassword {
   String message() default "Passwords don't match";
   Class<?>[] groups() default {}; 
   Class<? extends Payload>[] payload() default {};
}

PasswordValidatorImplementation(在单独的.java文件中):

public class CountryValidatorImplementation implements 
PasswordValidator<ValidPassword, Object> {

public PasswordValidatorImplementation() {

}

public boolean isValid(Object value, ConstraintValidatorContext context) {

    AccountData accountData = (AccountData) value;

    if(!accountData.password.equals(accountData.password)) {
      return false;  
    }
    //Not checking if account with login already exists in a DB for 
    //brevity
    return true;

}
}

主要方法中的用法:

  • 在我第一次设置密码并以编程方式重复Password时,不会导致NullPointerException:

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    AccountData accountData = new AccountData();
    accountData.password = "1234";
    accountData.repeatedPassword = "5678";
    Set<ConstraintViolation<AccountData>> constraintViolationSet = 
    validator.validate(accountData); 
    
  • 导致NullPointerException,因为我对其执行验证的密码为空:

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    AccountData accountData = new AccountData();
    Set<ConstraintViolation<AccountData>> constraintViolationSet = 
    validator.validate(accountData); 
    

由于这些注释,是否有可能在字段上执行@NotNull指示的验证并为isValid返回false(甚至更早引发Exception),以便检查是否不再需要任何AccountData字段? *也欢迎与弹簧相关的解决方案!

1 个答案:

答案 0 :(得分:0)

否,您不能及早停止验证。每个注释都会被处理,因此所有问题都可以一起报告。这比强迫用户反复尝试解决每个问题要好得多。

实际上,您应该编写几乎所有的自定义验证器,以将null视为有效。然后它们会更加有用,可以根据需要与@NotNull组合使用。

public boolean isValid(Object value, ConstraintValidatorContext context) {
    if (value == null) {
        return true;
    }
    // ...

由于验证器处理的字段值也可能为null,因此您可能需要这样的内容。

public class PasswordValidatorImpl implements PasswordValidator<ValidPassword, AccountData> {
    public boolean isValid(AccountData value, ConstraintValidatorContext context) {
        return value == null || Objects.equals(value.password, value.repeatedPassword);
    }
}