当我在方法中使用带有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应用程序中正常工作,因此您可以看到可能存在的差异。我至少假设以下几点:
@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
@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/