rob*_*ess 5 java validation annotations
我实现了一个自定义注释,@Password以对我的方法的参数执行验证setPassword()。注释的定义如下:
// Password.java
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import javax.validation.*;
@Target({METHOD, FIELD, PARAMETER, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
@Documented
public @interface Password {
String message() default PasswordValidator.message;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
验证器的当前实现是这样的:
// PasswordValidator.java
package utils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PasswordValidator implements ConstraintValidator<Password, String> {
/* Default error message */
final static public String message = "error.invalid.password";
/**
* Validator init
* Can be used to initialize the validation based on parameters
* passed to the annotation.
*/
public void initialize(Password constraintAnnotation) {
System.out.println("in initialize()");
}
public boolean isValid(String string, ConstraintValidatorContext constraintValidatorContext) {
System.out.println("in isValid()");
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在当前实现中,isValid()始终返回false。原因很快就会显现出来。
我对验证器的用法在一个类中User。为了简洁起见,我不会在此处发布整个源代码,但是相关部分是:
package models;
import utils.Password;
// other imports omitted
@Entity
@Table(name = "users", schema="public")
public class User {
@Required
private String password;
...
public void setPassword(@Password String clearPassword) {
try {
this.password = HashHelper.createPassword(clearPassword);
} catch (AppException e) {
e.printStackTrace();
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
基本思想是,我使用User类存储用户的哈希密码,但是在设置哈希密码之前,我(想)对未哈希的密码(即clearPassword)运行验证。
我遇到的问题是此验证没有进行。在当前的实现中,(根据我的理解)应该总是抛出a,ConstraintViolationException因为isValid()总是返回false,但是事实并非如此。
我已经通过在以下方面调用(在应用程序的另一部分中)来检查注释是否附加到方法参数上:
Method method = user.getClass().getMethod("setPassword", new Class[] { String.class });
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
System.out.println(method.getName() + ": " + parameterAnnotations[0][0]);
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
setPassword:@utils.Password(message=error.invalid.password, payload=[], groups=[])
Run Code Online (Sandbox Code Playgroud)
因此,这告诉我注释将应用于方法参数。但是我不明白为什么ConstraintViolationException我实际调用该方法时没有得到。我也从没看到我在这些方法中添加的initialize()或isValid()中的输出,以检查它们是否被触发。
作为另一项测试,我还将@Password注释添加到的成员变量password中User.class。这会导致ConstraintViolationException按预期方式抛出,例如,当我尝试持久化User对象时。
谁能阐明为什么方法参数上的注释无法正常工作?提前致谢!
我认为您在注释中缺少此声明Password:
ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;
Run Code Online (Sandbox Code Playgroud)
来自文档:
validationAppliesTo 在约束声明时使用,以阐明约束的目标(即带注释的元素、方法返回值或方法参数)。
元素validationAppliesTo 只能出现在通用约束和跨参数约束中,在这种情况下它是强制性的。如果违反这些规则,则会引发 ConstraintDefinitionException。
validationAppliesTo 参数的类型是 ConstraintTarget。默认值必须是 ConstraintTarget.IMPLICIT。