java – 没有执行方法参数的自定义注释

我已经实现了一个自定义注释@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.原因很快就会显现出来.

我对验证器的使用是在用户类中.为简洁起见,我不会在这里发布整个来源,但相关部分是:

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.我也从来没有看到我在这些方法中添加的输出“在initialize()”或“in is ismalid()”中作为检查它们是否被触发.

作为另一个测试,我还将@Password注释添加到User.class中的成员变量密码.这会导致按预期抛出ConstraintViolationException,例如当我尝试持久化User对象时.

任何人都可以解释为什么方法参数的注释不能正常工作?提前致谢!

最佳答案 我认为您在密码注释中缺少此声明:

ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;

来自文档:

validationAppliesTo is used at constraint declaration time to clarify what the constraint targets (i.e. the annotated element, the method return value or the method parameters).

The element validationAppliesTo must only be present for constraints that are both generic and cross-parameter, it is mandatory in this situation. A ConstraintDefinitionException is raised if these rules are violated.

The type of the validationAppliesTo parameter is ConstraintTarget. The default value must be ConstraintTarget.IMPLICIT.

点赞