繁体   English   中英

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

[英]Custom annotation on method argument is not being executed

我已经实现了一个自定义注释@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 我也从来没有看到我在这些方法中添加的输出“ 在initialize() ”或“ in is ismalid() ”中作为检查它们是否被触发。

作为另一个试验,我还添加了@Password注释到成员变量passwordUser.class 这会导致按预期抛出ConstraintViolationException ,例如,当我尝试持久保存User对象时。

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

我认为您在Password注释中缺少此声明:

ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;

来自文档:

validationAppliesTo在约束声明时使用,以阐明约束目标(即注释元素,方法返回值或方法参数)。

元素validationAppliesTo必须仅存在于通用和交叉参数的约束中,在这种情况下它是必需的。 如果违反这些规则,则会引发ConstraintDefinitionException。

validationAppliesTo参数的类型是ConstraintTarget。 默认值必须为ConstraintTarget.IMPLICIT。

它不会被验证,因为hibernate验证器验证用户对象而不是方法setPassword。 如果要抛出该异常,则必须获取ExecutableValidator实例,调用validateParameters方法,然后自行抛出ConstraintViolationException。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM