所以我的示例测试项目将显示完整的相关配置和代码:
约束注释:
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FooValidator.class)
public @interface FooValid {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
带注释的PoJo:
public class Foo {
@FooValid(message = "Test failed")
private Integer test;
[...]
}
带@Validated的注释服务:
@Service
@Validated
public class FooService {
private final Test test;
@Autowired
public FooService(final Test test) {
this.test = test;
}
public void foo(@Valid final Foo foo) {
this.test.test(foo);
}
}
JSR-303 ConstraintValidator:
public class FooValidator implements ConstraintValidator<FooValid, Integer> {
@Autowired
private ValidationService validationService;
@Override
public void initialize(final FooValid constraintAnnotation) {
// TODO Auto-generated method stub
}
@Override
public boolean isValid(final Integer value, final ConstraintValidatorContext context) {
// this.validationService is always NULL!
Assert.notNull(this.validationService, "the validationService must not be null");
return false;
}
}
注入验证服务:
@Service
public class ValidationService {
public void test(final Foo foo) {
System.out.println(foo);
}
}
Spring启动应用程序和配置:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(final String[] args) {
final ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
final FooService service = context.getBean(FooService.class);
service.foo(new Foo());
}
@Bean
public static LocalValidatorFactoryBean validatorFactory() {
return new LocalValidatorFactoryBean();
}
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
相关的maven pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.9.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.Application</start-class>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
我使用 LocalValidatorFactoryBean 和默认的 SpringConstraintValidatorFactory 。 但是为什么依赖注入不能在ConstraintValidator中工作而 ValidationService 无法自动装配?
顺便说一下,如果我不在服务中使用 @Validated ,请在spring或javax Validator接口的对面注入并手动调用&#34; validator.validate < / EM>&#34;依赖注入将起作用。但我不想手动调用每个服务中的验证方法。
非常感谢您的帮助:)
答案 0 :(得分:8)
我在Spring Boot环境中遇到了同样的问题,我发现Hibernate的内部实现不是配置Spring的内部实现。当应用程序启动时,调试器在Spring的工厂中占了一席之地,但后来在运行时就有了Hibernate的工厂。经过一些调试后,我得出的结论是 MethodValidationPostProcessor 得到了内部的一个。因此我将其配置如下:
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
请注意验证器的setter - 它完成了这项工作。
答案 1 :(得分:0)
我有同样的问题。问题出现是因为Hibernate正在寻找并应用验证器而不是Spring。因此,在配置Hibernate时需要将验证模式设置为NONE
:
@Bean(name="entityManagerFactory")
public LocalContainerEntityManagerFactoryBean
localContainerEntityManagerFactoryBean(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean lcemfb =
new LocalContainerEntityManagerFactoryBean();
lcemfb.setDataSource(dataSource);
lcemfb.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
lcemfb.setValidationMode(ValidationMode.NONE);
// Continue configuration...
如果您已经配置了LocalValidationFactoryBean,Spring将选择使用@Component
注释的任何验证器并自动装配它们。
答案 2 :(得分:0)
这对我有用。我不得不使用@Inject标记。
public class FooValidator implements ConstraintValidator<FooValid, Integer> {
private ValidationService validationService;
@Inject
public FooValidator(ValidationService validationService){
this.validationService = validationService;
}
@Override
public void initialize(final FooValid constraintAnnotation) {
// TODO Auto-generated method stub
}
@Override
public boolean isValid(final Integer value, final ConstraintValidatorContext context) {
// this.validationService is always NULL!
Assert.notNull(this.validationService, "the validationService must not be null");
return false;
}
}