如何使用Hibernate验证传入的参数?
在XML
中<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator"/>
</bean>
在Java中
@Validated
public class UserService
@Override
@NotNull
public User registerUser(@NotEmpty String name, String username, String password, boolean google, boolean facebook)
这种方法不起作用我称之为错误参数的方法,验证不起作用。
答案 0 :(得分:5)
问题澄清
在Spring-MVC 4中使用Hibernate Validator(HV)4.2时,例如依赖:
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.0.1'
compile 'org.springframework:spring-webmvc:4.0.3.RELEASE'
compile 'org.hibernate:hibernate-validator:4.2.0.Final'
runtime 'javax.servlet:jstl:1.1.2'
}
通过在配置文件中声明以下bean,可以告诉Spring自动使用HV来验证用@Validated
注释的类的方法调用(如在asker的例子中),
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
当调用目标的方法并且某些东西违反其约束时,抛出MethodConstraintViolationException
。例如,如果有人调用UserService#registerUser(...)
,将空字符串传递到注释为@NotEmpty
... The following constraint violations occurred: [MethodConstraintViolationImpl
[method=public abstract void foo.UserService.registerUser(java.lang.String),
parameterIndex=0, parameterName=arg0, kind=PARAMETER, message=may not be empty,
messageTemplate={org.hibernate.validator.constraints.NotEmpty.message}, ...
但问题是如果你将依赖关系从上面改为
dependecies {
providedCompile 'javax.servlet:javax.servlet-api:3.0.1'
compile 'org.springframework:spring-webmvc:4.0.3.RELEASE'
compile 'org.hibernate:hibernate-validator:5.1.0.Final' //**note the change here**
runtime 'javax.servlet:jstl:1.1.2'
}
然后你会收到一个错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'org.springframework.validation.beanvalidation.MethodValidationPostProcessor#0'
defined in class path resource [spring/config/web/main-config.xml]: Invocation of init
method failed; nested exception is javax.validation.ValidationException: Unable to
instantiate Configuration.
<强>解决方案强>
在类路径中添加2个额外的依赖项,如下所示,
dependecies {
providedCompile 'javax.servlet:javax.servlet-api:3.0.1'
providedCompile 'javax.el:el-api:2.2'
providedCompile 'org.glassfish.web:el-impl:2.2'
compile 'org.springframework:spring-webmvc:4.0.3.RELEASE'
compile 'org.hibernate:hibernate-validator:5.1.0.Final' //**note the change here**
runtime 'javax.servlet:jstl:1.1.2'
}
验证将恢复生机。但是这一次,而不是MethodConstraintViolationException
,它会提升ConstranitViolationException
,而不会详细说明违反的内容。
我不确定Spring如何在内部管理这个问题,并且您可以从此异常中展开违规详细信息。 HV 5不再支持MethodConstraintViolationException
及其亲属,例如MethodValidator
,MethodConstraintViolation
。这与Bean Validation 1.1 specification有关,它在BV 1.0的方法级验证中有一些变化。我建议使用方面和ExecutableValidator
(而不是旧的MethodValidator
)自行创建验证服务,如HV's Reference guide中所述。
请注意,如果您尝试获取此类验证器,
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();
你可能会ValidationException: Unable to instantiate configuration.
我可以通过这个来解决这个问题
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();
答案 1 :(得分:4)
除了maven pom文件中的spring和其他项目依赖项之外,我还包括以下内容。
<properties>
<hibernate.version>4.3.1.Final</hibernate.version>
<hibernate.validator.version>5.1.0.Final</hibernate.validator.version>
<javax.el.version>3.0.0</javax.el.version>
<asm.version>3.3.1</asm.version>
</properties>
<dependencies>
<!-- Hibernate et al-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>${javax.el.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>${javax.el.version}</version>
</dependency>
<!-- asm allows hibernate validator to retrieve method parameter names when reporting method validation
without this you just get arg0 instead of argument name -->
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
</dependencies>
在我的弹簧配置中,我设置了
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("validation");
messageSource.setCacheSeconds(1);
return messageSource;
}
@Bean
LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource());
validator.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
return validator;
}
@Bean
@Autowired
MethodValidationPostProcessor getValidationPostProcessor(LocalValidatorFactoryBean validator) {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setValidator(validator);
return processor;
}
LocalVariableTableParameterNameDiscoverer与ASM一起使用,在ConstraintViolationException中提供适当的参数名称,当验证失败时将抛出该参数名称。
答案 2 :(得分:0)
显然Spring建议不要使用ExecutableValidator而是使用MethodValidationInterceptor,请参阅javadoc:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
答案 3 :(得分:0)
对于当前版本,您不必添加“asinkxcoswt”在https://stackoverflow.com/a/23384229/6028739中写入的所有bean。
到你的pom.xml中添加:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
将此行添加到您的应用程序上下文中:
<bean id="validationFactory" class="javax.validation.Validation"
factory-method="buildDefaultValidatorFactory" />
所有使用@Validated注释的实体现在都已经过验证,并向javax.validation.ConstraintViolationException
投掷违反约束的列表,其中包含详细信息,例如:
javax.validation.ConstraintViolationException: Validation failed for classes [com.example.Class] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must be greater than or equal to 0', propertyPath=amount, rootBeanClass=class com.example.Class, messageTemplate='{javax.validation.constraints.Min.message}'}
]