0

在我的自定义注释中,我正在使用我将允许邮件的域

@Documented
@Constraint(validatedBy = ValidEmail.CheckIfValidMail.class)
//@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
//@Repeatable(List.class)
@Retention(RUNTIME)
@Component
public @interface ValidEmail {

    String message() default "Invalid String !!";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    @Documented
    @interface List {

        ValidEmail[] value();
    }

    @Component
    public class CheckIfValidMail implements ConstraintValidator<ValidEmail, String> {

        @Autowired
        UserServiceImplOld userServiceImpl;

//      @Value("${app.mail.allowedDomains:gmail}")
        private String[] allowedDomainsForMail;

        @Value("${app.mail.allowedDomains:gmail}")
        public void setAllowedDomainsForMail(String[] allowedDomainsForMail) {
            this.allowedDomainsForMail = allowedDomainsForMail;
        }

//      private String[] allowedDomainsForMail = new String[] { "gmail", "rediffmail", "yahoo" };

        protected String message;

        @Override
        public void initialize(ValidEmail validEmail) {
            this.message = validEmail.message() + "  Allowed Domain(s): " + Arrays.toString(allowedDomainsForMail);
        }

        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            if (value == null)
                return true;
            String allowedDomainRegEx = String.join("|", allowedDomainsForMail);
            String mailRegex = "^(?i)[A-Za-z0-9+_.-]+@(?:" + allowedDomainRegEx + ")\\.(?:.*)$";
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
            return value.matches(emailRegex);
        }

    }
}

如果我从 rest API 调用它,每次值都在那里,但是如果我从代码中显式调用验证,我可以在调试中看到 allowedMailDomains 值为 null

但是,如果我不从属性文件和硬编码中获取,那么它就像这样同时工作

对象

@Data //lombok
public class UserDto{
    @ValidEmail(message = "Wrong emailId format !!")
    private String emailId;

    @NotNull
    private Boolean isLoginAllowed;

}

在实施中

UserDto addUserDto = new UserDto();
addUserDto.setEmailId("satish");
addUserDto.setisLoginAllowed(false);
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
System.out.println("Validating :-\n" + validator.validate(addUserDto));

因此,在验证时转到 ValidMail 接口,并且 allowedMailDomains 值为 null

4

3 回答 3

0

尝试注册LocalValidatorFactoryBean并使用它而不是Validation.buildDefaultValidatorFactory(). LocalValidatorFactoryBean应该允许您在验证器中获得依赖注入的好处。

UPD:https ://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation-beanvalidation-spring-constraints

默认情况下,LocalValidatorFactoryBean 配置一个 SpringConstraintValidatorFactory,它使用 Spring 创建 ConstraintValidator 实例。这使您的自定义 ConstraintValidators 可以像任何其他 Spring bean 一样从依赖注入中受益。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class ValidatorConfiguration {
    @Bean
    public ValidatorFactory localValidatorFactoryBean() {
        return new LocalValidatorFactoryBean();
    }
}

然后在你的实现类中自动装配这个bean:

@Autowired
private ValidatorFactory validatorFactory;

并使用它代替DefaultValidatorFactory

Validator validator = validatorFactory.getValidator();
validator.validate(addUserDto);
于 2019-11-16T13:27:18.423 回答
-1

要注入属性allowedMailDomains,您的类CheckIfValidMail必须是一个 bean。因此,如果您将@Component注释(例如)添加到您的类中,问题将得到解决。

于 2019-11-16T13:13:42.677 回答
-1

所以这里是问题:

  • RESTAPI 中运行代码时,您在 Spring 容器中运行,该容器将 初始化CheckIfValidMail为 a Component,然后从Spring容器中获取所需的所有值和所有内容。

  • 当您以编程方式初始化它时,它没有被初始化为 a Component,也没有Container从中获取@Value,我什至怀疑Properties在第二种情况下完全加载了(我看不到整个代码,所以我没有肯定知道)。

如果没有完整的上下文,这是我头顶的一个解决方案:

在验证器中执行以下操作:

private String[] allowedMailDomains;

@Value("${poss.mail.allowedDomains:gmail}")
public void setAllowedMailDomains(String[] allowedMailDomains) {
    this.allowedMailDomains = allowedMailDomains;
}

然后在您的程序验证中设置该值,这应该可以工作。

否则,只需在容器中初始化它就可以修复它。

于 2019-11-16T14:03:24.043 回答