2014-02-11 4 views
3

Как проверить входящие аргументы с Hibernate?Проверка аргумента Spring 4 и Hibernate 5

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

Этот подход не работает я вызвать метод с Params ошибок и проверки не работает.

+0

Здесь нет никаких вопросов. – chrylis

+0

В hibernate 4.2.0 есть packacge org.hibernate.validator.method для методов malidate, как validate с hibertnate validator 5.0.3 –

ответ

5

Вопрос Разъяснение

При использовании 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' 
} 

можно сказать Spring автоматически использовать HV для проверки вызовов методов классов, аннотированных @Validated (как в примере Аскера), объявляя следующие бобы в файле конфигурации,

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> 

Когда метод цели вызывается и имеет что-то, что нарушает его ограничения, бросается MethodConstraintViolationException. Например, будет поднят что-то вроде этого, если один happeded позвонить 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 к следующим классам,

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 без каких-либо подробностей о том, что было нарушено.

Я не уверен, как Весна справляется с этим внутренне, и вы можете развернуть детали нарушения из этого Исключения. 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(); 
4

I включают следующее в дополнение к весной и другими зависимостями проекта в файле 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> 

В моей 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 работает с ASM, чтобы дать правильные имена параметров в ConstraintViolationException, который будет выброшен при сбое проверки.

+0

У меня возникла та же проблема. Это не работает, потому что вы инициализировали источник источника сообщений. Он работает, потому что Validation является именем свойства по умолчанию для спящего режима. Вы можете удалить messageSource, и он все равно будет работать. – Gazeciarz

0

Для текущей версии вы не должны добавить все бобы, которые «asinkxcoswt» писали в https://stackoverflow.com/a/23384229/6028739.

К вашему 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}'} 
] 
+0

Неплохо, вам не нужно использовать @Validated аннотации. Валидации работают и без него. – KHanusova

+0

Вам нужны только '@ Validated' для' @ RequestParam'. Как указывает JavaDoc: «Может использоваться, например, с аргументами методов обработчика Spring MVC». – Dormouse

Смежные вопросы