@@值字段在第二次调用类方法时显示为空

问题描述 投票:0回答:3

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

@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

但是,如果我不使用属性文件和硬编码,则这两个时间都可以正常工作

Dto对象

@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

java spring-boot spring-properties
3个回答
0
投票

所以这里是问题:

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

  • 以编程方式初始化它时,它没有初始化为Component,也没有Container来获取@Value,我什至会怀疑Properties是否已完全加载在第二种情况下(我看不到完整的代码,所以我不确定)。

没有完整的上下文,这是我头上的解决方案:

在验证器中执行此操作:

private String[] allowedMailDomains;

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

然后在程序验证中设置该值,然后该值将起作用。

否则,只需将其初始化在容器中,然后应将其修复。


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);

-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.