由于您只提供了控制器方法中的代码,因此我添加了一些额外信息,以便在 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 的使用,请参阅此相关问题/答案。
在上面的错误日志中,如果我省略了BindingResult/Errors 参数,您会看到ErrorController 是报告验证错误的那个,实际上那是我使用@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。