当我在方法中使用带有BindingResult批注的@Validated时,验证不起作用。如果我从方法参数中删除BindingResult,它将正常工作。我使用了@ControllerAdvice

知道为什么它不起作用吗?

我的代码如下:

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

根据Validation, Data Binding, and Type Conversion documentation
任何验证消息将自动添加到活页夹的BindingResult中。

删除它不会有影响,对吗?

最佳答案

由于您仅从控制器方法中提供了代码,因此,我添加了一些其他信息,以便使验证在Spring 4应用程序中正常工作,因此您可以看到可能存在的差异。我至少假设以下几点:

  • 在您的类路径中包括bean-validation-api JAR。这将为您提供注释。
  • 在类路径中包含Bean验证实现JAR(例如,参考实现hibernate-validator)。这将启用验证框架。
  • 您的请求映射可以是以下形式之一:

  • @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
    

    或者,如果使用validation groups:
    @RequestMapping(method = RequestMethod.POST)
    public String dologin(@Validated({ User.Login.class }) @ModelAttribute("userForm") User user, final BindingResult bindingResult) throws Exception
    

  • 您在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;
    

    或者,如果使用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;
    

  • 您的邮件属性应在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.
    

    确保您的Bean Validation specification版本与您的实现版本匹配。 Bean Validation API 2.0于2017年8月发布。Bean Validation 2.0参考实现为Hibernate Validation Engine 6.0

    如果方法参数中存在验证错误,则会将其添加到BindingResult中。另外,您可以使用Errors代替BindingResult-API本质上是相同的。在我上面的实现中,这两个都等效地工作。

    但是,如果我将该参数保留在控制器方法之外,那么(从日志记录中)我会看到触发了验证并引发了相应的错误,并且消息键到其属性的映射成功,但是呈现了“服务器错误”页面我期望的观点。有关此参数要求的其他信息,请参见BindingResult/Errors parameter上的相关问题。
    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)
    

    在上述所有组合中,我看到了非常一致的行为。

    我注意到的一个区别是您在示例中使用的是@ControllerAdvice。我的大多数控制器都使用 @Controller 批注(本地控制器错误),而不使用 @ControllerAdvice (用于全局错误,例如用于呈现HTTP 404或500错误页面)。有关 @ControllerAdvice 的使用,请参见此相关问题/答案。

    在上面的错误日志中,如果我不考虑ErrorController / BindingResult参数,则可以看到Errors是报告验证错误的代码,而这确实是我的控制器类,它使用@ControllerAdvice注释而不是@Controller。通过在登录控制器上使用@ControllerAdvice,您可能会干扰正常的错误处理。

    由于您使用的是Hibernate-specific @Validated 组验证批注而不是JSR-303/349/380规范 @Valid 批注,因此您使用的实现之间可能会有一些差异(我猜是版本5,它符合API 1.1)。我正在使用6.0.2版本,该版本符合新的(2017年8月)Bean Validation Framework API 2.0

    关于java - Spring 4 @Validation注释与BindingResult不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42852886/

    10-13 04:30