我已经实现了自定义注释@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 {};
}
验证器的当前实现是这样的:
// 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;
}
}
请注意,在当前实现中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();
}
}
...
}
基本思想是我使用User类为用户存储散列密码,但在设置散列密码之前,我(希望)对未散列的密码(即clearPassword
)运行验证。
我遇到的问题是没有进行此验证。在当前的实现中,它应该(根据我的理解)总是抛出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]);
产生以下输出:
setPassword:@utils.Password(message=error.invalid.password, payload=[], groups=[])
所以这告诉我注释正在应用于方法参数。但我无法理解为什么当我实际调用该方法时,我没有得到ConstraintViolationException
。我也从来没有在这些方法中看到输出“ in initialize()”或“ in is ismalid()”作为检查以查看它们是否被解雇
作为另一项测试,我还将@Password
注释添加到password
中的成员变量User.class
。这导致ConstraintViolationException
按预期抛出,例如当我试图坚持User
对象时。
任何人都可以解释为什么方法参数的注释不能正常工作?提前谢谢!
答案 0 :(得分:2)
我认为您在Password
注释中遗漏了此声明:
ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;
来自文档:
validationAppliesTo在约束声明时使用,以阐明约束目标(即注释元素,方法返回值或方法参数)。
元素validationAppliesTo必须仅存在于通用和交叉参数的约束中,在这种情况下它是必需的。如果违反这些规则,则会引发ConstraintDefinitionException。
validationAppliesTo参数的类型是ConstraintTarget。默认值必须为ConstraintTarget.IMPLICIT。
答案 1 :(得分:0)
它不会被验证,因为hibernate验证器验证用户对象而不是方法setPassword。如果要抛出该异常,则必须获取ExecutableValidator实例,调用validateParameters方法,然后自行抛出ConstraintViolationException。