当我在方法中使用带有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
。
如果我删除它会没有影响,对吗?
答案 0 :(得分:1)
由于您只提供了控制器方法的代码,因此我添加了一些其他信息,以便在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
注释,因此您使用的实现之间可能存在一些差异(I'猜测版本5,符合API 1.1)。我使用的是6.0.2版,符合新版(2017年8月)Bean Validation Framework API 2.0。
答案 1 :(得分:1)
Hibernate Validator 6 不能与 Spring 4 一起开箱即用,因为 Spring 4 的 LocalValidatorFactoryBean 还没有使用 Java 的 Service Provider 机制来发现 Validator 实现,因此您需要自己创建验证器,指定实施。
使用 @EnableWebMvc
时:
@Bean
public javax.validation.Validator localValidatorFactoryBean() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setProviderClass("org.hibernate.validator.HibernateValidator");
return bean;
}
或在 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>