这个例子有点人为; 我简化了它以删除无关的细节,并专注于我遇到的问题.我有一个看起来像这样的验证器:
@Component
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
UsernameService usernameService;
@Override
public void initialize(UniqueUsername uniqueUsername) {
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return !usernameService.exists(s);
}
}
Run Code Online (Sandbox Code Playgroud)
我从我的控制器调用验证器,如下所示:
@RequestMapping
public void checkUsername(Model model, User user) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username");
model.addAttribute("error", constraintViolations.size() > 0);
}
Run Code Online (Sandbox Code Playgroud)
但是,我一直有NullPointerException
例外.我在验证器添加一个断点,并看到usernameService
了null
.为什么不进行自动装配?最初我认为这是因为我没有注释验证器@Component
,但即使在注释它之后我仍然有同样的问题.该UsernameService
班已经标注了@Service
,我可以验证它的构造函数获取调用.
我是Spring的新手,所以我甚至不确定将服务连接到验证器是否可以.我究竟做错了什么?
我在自定义约束验证器中有bean自动装配的问题.使用Spring的LocalValidatorFactoryBean不会给出约束验证器实例.JSR-303提供程序是hibernate-validator 4.2.0.Final.
Spring配置摘录:
<!-- JSR 303 validation -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
Run Code Online (Sandbox Code Playgroud)
自定义约束验证器:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.model.Subject;
import com.services.SomeTypeService;
public class ReadOnlyValidator implements ConstraintValidator<ReadOnly, String> {
@Autowired
private SomeTypeService someTypeService;
@Override
public void initialize(ReadOnly constraintAnnotation) { }
@Override
public boolean isValid(String type, ConstraintValidatorContext context) {
try {
if (null != type) {
return !someTypeService.isReadonly(type);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
注解:
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import …
Run Code Online (Sandbox Code Playgroud) 我创建了一个小示例项目,以显示我在Spring Boot验证配置及其与Hibernate集成时遇到的两个问题.我已经尝试过我发现的有关该主题的其他回复,但遗憾的是它们对我不起作用或者要求禁用Hibernate验证.
我想使用自定义的Validator实现ConstraintValidator<ValidUser, User>
并注入我的UserRepository
.同时我想保持Hibernate的默认行为,在更新/持久化期间检查验证错误.
我在这里写的是应用程序的完整主要部分.
自定义配置
在这个类中,我使用自定义设置自定义验证器MessageSource
,因此Spring将从文件中读取消息resources/messages.properties
@Configuration
public class CustomConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/messages");
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setValidationMessageSource(messageSource());
return factoryBean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
}
Run Code Online (Sandbox Code Playgroud)
如果不是自定义验证器,那么bean没什么特别之处@ValidUser
@ValidUser
@Entity
public class User extends AbstractPersistable<Long> {
private static …
Run Code Online (Sandbox Code Playgroud) 我有一个基于Spring的webapp.我在控制器中使用了几个带注释@Repository,@ Transaction的存储库类.那部分工作正常.
我创建了一个Custom Constraint Validator,它必须访问存储库.现在我无法理解为什么Repository为null.我尝试使用@Component注释来注释验证器.我的基本包包含所有这些类是在xml的一部分.那么我还应该做些什么来确保存储库依赖注入工作.这就是我的Constraint验证器的样子.
public class DonorTypeExistsConstraintValidator implements
ConstraintValidator<DonorTypeExists, DonorType> {
@Autowired
private DonorTypeRepository donorTypeRepository;
@Override
public void initialize(DonorTypeExists constraint) {
}
public boolean isValid(DonorType target, ConstraintValidatorContext context) {
System.out.println("donorType: " + target);
if (target == null)
return true;
try {
if (donorTypeRepository.isDonorTypeValid(target.getDonorType()))
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public void setDonorRepository(DonorTypeRepository donorTypeRepository) {
this.donorTypeRepository = donorTypeRepository;
}
}
Run Code Online (Sandbox Code Playgroud)
更新
包扫描配置:
<context:annotation-config />
<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />
<context:component-scan …
Run Code Online (Sandbox Code Playgroud) 问题已经在这里解决,但对我不起作用(我猜不是同一个 spring boot 版本)这个
尝试编写自定义约束验证器,以在持久化之前检查帐户电子邮件是否存在。
@Email
@NotNull
@NotBlank
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueCompteEmailValidator.class)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface UniqueCompteEmail {
String message() default "{com.mssmfactory.bacsimulator.uniquecompteemail.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
// ------------------------------------------------ --------------------------
public class UniqueCompteEmailValidator implements ConstraintValidator<UniqueCompteEmail, String> {
@Autowired
private CompteRepository compteRepository;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && this.compteRepository.findByEmail(value) == null;
}
}
Run Code Online (Sandbox Code Playgroud)
// ------------------------------------------------ --------------------------
@Configuration
public class OtherConfigurations {
//----
@Bean …
Run Code Online (Sandbox Code Playgroud) validation hibernate dependency-injection spring-data-jpa spring-boot