Java Spring 4 和 Hibernate 5 方法参数验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21696146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring 4 and Hibernate 5 method argument validation
提问by Rinat Mukhamedgaliev
How validate incoming arguments with Hibernate ?
如何使用 Hibernate 验证传入参数?
In XML
在 XML 中
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator"/>
</bean>
In Java
在 Java 中
@Validated
public class UserService
@Override
@NotNull
public User registerUser(@NotEmpty String name, String username, String password, boolean google, boolean facebook)
This approach not work i call method with error params and validation not work.
这种方法不起作用我用错误参数调用方法并且验证不起作用。
采纳答案by asinkxcoswt
Question Clarification
问题澄清
When using Hibernate Validator (HV) 4.2 with Spring-MVC 4, e.g. with dependencies:
将 Hibernate Validator (HV) 4.2 与 Spring-MVC 4 一起使用时,例如具有依赖项:
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'
}
one can tell Spring to automatically use HV to validate method calls of classes annotated with @Validated
(as in asker's example) by declaring following beans in the configuration file,
可以@Validated
通过在配置文件中声明以下 bean来告诉 Spring 自动使用 HV 来验证使用注释的类的方法调用(如提问者的示例),
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
When the target's method get called and has somethings that violates its constraints, the MethodConstraintViolationException
is thrown. For example, something like this will be raised if one happeded to call UserService#registerUser(...)
, passing an empty String to where annotated with @NotEmpty
当目标的方法被调用并且有一些违反其约束的东西时,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}, ...
But the problem is if you change the dependencies from above to
但问题是,如果您将依赖项从上面更改为
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'
}
then you will get an error:
那么你会得到一个错误:
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.
Solution
解决方案
Add 2 additional dependecies to the classpath as follows,
向类路径添加 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'
}
And the validation will comeback to life. But this time, instead of MethodConstraintViolationException
, it raises ConstranitViolationException
with no details of what has been violated.
验证将恢复生机。但这一次,而不是MethodConstraintViolationException
,它提出ConstranitViolationException
了没有被违反的细节。
I am not sure how Spring manage this internally and wheter you can unfold the violation details out of this Exception. HV 5 no longer supports MethodConstraintViolationException
and its relatives, e.g. MethodValidator
, MethodConstraintViolation
. This is something to do with Bean Validation 1.1 specification, which has some changes in method-level validation from BV 1.0. I suggest creating the validation service yourself using aspect and with ExecutableValidator
(instead of the old MethodValidator
) as explained in HV's Reference guide.
我不确定 Spring 如何在内部管理它,以及您是否可以从这个异常中展开违规细节。HV 5 不再支持MethodConstraintViolationException
及其亲属,例如MethodValidator
,MethodConstraintViolation
。这与Bean Validation 1.1 规范有关,它在方法级验证方面与 BV 1.0 有一些变化。我建议自己使用 aspect 和 with ExecutableValidator
(而不是旧的MethodValidator
)创建验证服务,如HV 的参考指南 中所述。
Note that you if you try to obtain the validator like this,
请注意,如果您尝试像这样获取验证器,
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();
you may get ValidationException: Unable to instantiate configuration.
I can solve this problem by do this
你可能会知道ValidationException: Unable to instantiate configuration.
我可以通过这样做来解决这个问题
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();
回答by Magnus Smith
I include the following in addition to spring and other project dependencies in the maven pom file.
除了 spring 和 maven pom 文件中的其他项目依赖项之外,我还包括以下内容。
<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>
In my java config for spring I set
在我为 spring 设置的 java 配置中
@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 works with ASM to give proper parameter names in the ConstraintViolationException that will be thrown when validation fails.
LocalVariableTableParameterNameDiscoverer 与 ASM 一起工作,在 ConstraintViolationException 中给出正确的参数名称,当验证失败时将抛出该异常。
回答by Serkan Kaba
Apparently Spring suggests not to use ExecutableValidator but MethodValidationInterceptor instead, see javadoc: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
显然 Spring 建议不要使用 ExecutableValidator 而是 MethodValidationInterceptor,请参阅 javadoc:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
回答by KHanusova
For current version you don't have to add all beans that "asinkxcoswt" wrote in https://stackoverflow.com/a/23384229/6028739.
对于当前版本,您不必添加“asinkxcoswt”在https://stackoverflow.com/a/23384229/6028739 中写入的所有 bean 。
To your pom.xml add this:
在您的 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>
Add this line to your application context:
将此行添加到您的应用程序上下文中:
<bean id="validationFactory" class="javax.validation.Validation"
factory-method="buildDefaultValidatorFactory" />
All entities annotated with @Validated are now validated and throw javax.validation.ConstraintViolationException
with list of constraint violations with details e.g.
所有用@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}'}
]