简体   繁体   English

带有 BindingResult 的 Spring 4 @Validation 注释不起作用

[英]Spring 4 @Validation annotation with BindingResult is not working

When I use BindingResult with @Validated annotation in a method, validation is not working.当我在方法中使用带有@Validated注释的BindingResult时,验证不起作用。 If I remove BindingResult from the method parameters, it works fine.如果我从方法参数中删除BindingResult ,它工作正常。 I used @ControllerAdvice .我使用了@ControllerAdvice

Any idea why is it not working?知道为什么它不起作用吗?

My code is below:我的代码如下:

public ResponseEntity<?> dologin(
        @Validated({ Group.Login.class }) @RequestBody User user,
        BindingResult errors)
{
    // somecode
}

As per the Validation, Data Binding, and Type Conversion documentation , any validation message will be automatically added to the binder's BindingResult .根据验证、数据绑定和类型转换文档,任何验证消息都将自动添加到绑定器的BindingResult

There will be no impact if I remove it, right?去掉不会有影响吧?

Since you only provided the code from your controller method, I'm adding some additional information that is needed in order to get validation working in a Spring 4 application, so you can see where any differences might be.由于您只提供了控制器方法中的代码,因此我添加了一些在 Spring 4 应用程序中进行验证所需的附加信息,以便您可以看到可能存在的差异。 I am minimally assuming the following:我至少假设以下内容:

  1. Include the bean-validation-api JAR in your classpath.在类路径中包含bean-validation-api JAR。 This gets you the annotation.这将为您提供注释。
  2. Include a Bean Validation implementation JAR (eg, the reference implementation, hibernate-validator ) in your classpath.在您的类路径中包含一个 Bean 验证实现 JAR(例如,参考实现hibernate-validator )。 This enables the validation framework.这将启用验证框架。
  3. Your request mapping could be of one the following forms:您的请求映射可以是以下形式之一:

@RequestMapping(method = RequestMethod.POST)
public String dologin(@Valid @ModelAttribute("userForm") User user, final BindingResult bindingResult) throws Exception

@RequestMapping(method = RequestMethod.POST)
public String dologin(@Validated @ModelAttribute("userForm") User user, final BindingResult bindingResult) throws Exception

or, if using validation groups :或者,如果使用验证组


@RequestMapping(method = RequestMethod.POST)
public String dologin(@Validated({ User.Login.class }) @ModelAttribute("userForm") User user, final BindingResult bindingResult) throws Exception

  1. Your annotation in the User class should be inline with message property keys:您在 User 类中的注释应该与消息属性键内联:

@NotBlank(message = "{firstName.required}")
@Size(min = 2, max = 24, message = "{firstName.size}")
@Pattern(regexp = "^[’' \\.\\-\\p{L}\\p{M}]*$", message = "{firstName.format}")
private String firstName;

or, if using validation groups :或者,如果使用验证组


public interface Login extends Default {}

@NotBlank(message = "{firstName.required}", groups = {Login.class})
@Size(min = 2, max = 24, message = "{firstName.size}", groups = {Login.class})
@Pattern(regexp = "^[’' \\.\\-\\p{L}\\p{M}]*$", message = "{firstName.format}", groups = {Login.class})
private String firstName;

  1. Your message properties should be in src/main/resources :您的消息属性应该在src/main/resources

firstName.required=First name is required.
firstName.size=First name must be between {min} and {max} characters long.
firstName.format=First name may contain only letters, apostrophes, spaces and hyphens.

Make sure your Bean Validation specification version matches your implementation version.确保您的Bean 验证规范版本与您的实现版本相匹配。 Bean Validation API 2.0 was released in August 2017. The Bean Validation 2.0 Reference Implementation is Hibernate Validation Engine 6.0 . Bean Validation API 2.0于 2017 年 8 月发布。 Bean Validation 2.0 参考实现是Hibernate Validation Engine 6.0

The validation errors will be added to the BindingResult if that is present in the method parameters.如果BindingResult存在于方法参数中,则验证错误将被添加到BindingResult中。 Alternatively, you can use Errors in place of BindingResult - the API is essentially the same.或者,您可以使用Errors代替BindingResult - API 本质上是相同的。 Both of these work equivalently in my above implementation.在我上面的实现中,这两个工作等效。

However, if I leave the parameter out of my controller method, I see (from logging) that the validation is triggered and the appropriate errors are raised and the mapping of my message keys to their properties succeed, but my Server Error page is rendered instead of my expected view.但是,如果我将参数从我的控制器方法中删除,我会看到(从日志记录中)触发了验证并引发了适当的错误,并且我的消息键到其属性的映射成功,但我的服务器错误页面被呈现我预期的观点。 For additional information on the requirement of this parameter, see this related question on the BindingResult/Errors parameter .有关此参数要求的其他信息,请参阅有关BindingResult/Errors 参数的相关问题。


Aug 31, 2017 2:21:56 PM com.test.spring.controller.ErrorController handleException
SEVERE: Server Error
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'userForm' on field 'firstName': rejected value []; codes [Size.userForm.firstName,Size.firstName,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userForm.firstName,firstName]; arguments []; default message [firstName],24,2]; default message [First name must be between 2 and 24 characters long.]
Field error in object 'userForm' on field 'firstName': rejected value []; codes [NotBlank.userForm.firstName,NotBlank.firstName,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userForm.firstName,firstName]; arguments []; default message [firstName]]; default message [First name is required.]
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:117)

I see very consistent behavior in all of the above combinations.我在上述所有组合中都看到了非常一致的行为。

One difference I note is that you are using @ControllerAdvice in your example.我注意到的一个区别是您在示例中使用了@ControllerAdvice Most of my controllers use the @Controller annotation (local controller errors), not @ControllerAdvice (used for global errors, such as for rendering HTTP 404 or 500 error pages).我的大多数控制器使用@Controller注释(本地控制器错误),而不是@ControllerAdvice (用于全局错误,例如渲染 HTTP 404 或 500 错误页面)。 See this related question/answer for the use of @ControllerAdvice .有关@ControllerAdvice的使用,请参阅此相关问题/答案。

In the above error log, you see that ErrorController is the one reporting the validation errors if I leave out the BindingResult / Errors parameter, and indeed that is my controller class that uses @ControllerAdvice annotation instead of @Controller .在上面的错误日志中,如果我省略了BindingResult / Errors参数,您会看到ErrorController是报告验证错误的BindingResult ,实际上这是我的控制器类,它使用@ControllerAdvice批注而不是@Controller By using @ControllerAdvice on your login controller you may be interfering with normal error handling.通过在登录控制器上使用@ControllerAdvice ,您可能会干扰正常的错误处理。

Since you are using the Hibernate-specific @Validated group validation annotation instead of the JSR-303/349/380 specification@Valid annotation, there may be some differences between the implementation you used (I'm guessing version 5, which conformed to API 1.1).由于您使用的是特定Hibernate 的@Validated组验证注释,而不是JSR-303/349/380规范的@Valid注释,因此您使用的实现之间可能存在一些差异(我猜是版本 5,它符合 API 1.1)。 I am using version 6.0.2, which conforms to the new (August 2017) Bean Validation Framework API 2.0 .我使用的是 6.0.2 版,它符合新的(2017 年 8 月) Bean Validation Framework API 2.0

Hibernate Validator 6 does not work out of the box with Spring 4 because Spring 4's LocalValidatorFactoryBean does not yet use Java's Service Provider mechanism to discover the Validator implementation, so you need to create the validator yourself specifying the implementation. Hibernate Validator 6 不能与 Spring 4 一起开箱即用,因为 Spring 4 的LocalValidatorFactoryBean还没有使用 Java 的服务提供者机制来发现 Validator 实现,因此您需要自己创建验证器来指定实现。

When using @EnableWebMvc :使用@EnableWebMvc

@Bean
public javax.validation.Validator localValidatorFactoryBean() {
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setProviderClass("org.hibernate.validator.HibernateValidator");
    return bean;
}

Or in XML:或者在 XML 中:

<mvc:annotation-driven validator="validator-adapter"/>

<bean id="validator-adapter" 
  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass"
              value="org.hibernate.validator.HibernateValidator" />
</bean>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM