通过使用@Valid注释无法本地检测到JSR-303错误 [英] JSR-303 errors not detected natively by using the @Valid annotation
问题描述
为什么@Valid注释不能本地捕获我的JSR-303注释,但是可以使用以下方法捕获它们:
How come the @Valid annotation does not catch my JSR-303 annotations natively, but do catch them using the following method:
WebConfig.java
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
String[] strBaseNames = {
"resources.messages.layout.LayoutResources",
"resources.messages.layout.MenuResources",
"resources.messages.global.GlobalResources"
};
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setBasenames(strBaseNames);
return messageSource;
}
@Bean
public LocalValidatorFactoryBean jsr303Validator() {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(this.messageSource());
return localValidatorFactoryBean;
}
UserController.java
@Controller
@RequestMapping(value = "/security/user", method = RequestMethod.GET)
public class UserController {
@Autowired
private SecurityService securityService;
@Autowired
SessionObject sessionObject;
@Autowired
@Qualifier("jsr303Validator") Validator validator;
@RequestMapping(value = "/edit/validate", method = RequestMethod.POST)
public String validateEdit( @ModelAttribute @Valid User user,
BindingResult result,
Model model) {
String strViewName = "common/error";
validator.validate(user, result);
if(result.hasErrors()) {
strViewName = "user/userEdit";
} else {
... update work ...
strViewName = "user/success";
}
return strViewName;
}
如果仅使用@Valid批注,则result.hasErrors()始终为空,因此最终会出现ConstraintViolationException(请参见下文).但是我想让它仅使用@Valid注释工作,而不必在我要实现一些JSR-303验证的每个控制器中自动连接jsr303validator bean.
If I only use the @Valid annotation, result.hasErrors() is always empty, so I end up having an ConstraintViolationException (see below), which is expected. But I would like to have it working using the @Valid annotation only, without having to autowire my jsr303validator bean in each controller I want to implement some JSR-303 validations.
约束违规日志跟踪
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [spring4base.model.security.User] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='error.firstname.notnull', propertyPath=strFirstName, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.firstname.notnull'}
ConstraintViolationImpl{interpolatedMessage='error.userid.notnull', propertyPath=strUserId, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.userid.notnull'}
ConstraintViolationImpl{interpolatedMessage='error.lastname.notnull', propertyPath=strLastName, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.lastname.notnull'}
]
User.java
@NotBlank(message = "error.userid.notnull")
@Size(min = 0, max = 14, message = "error.firstname.length")
private String strUserId = "";
@NotBlank(message = "error.firstname.notnull")
@Size(min = 0, max = 50, message = "error.firstname.length")
private String strFirstName = "";
@NotBlank(message = "error.lastname.notnull")
@Size(min = 0, max = 50, message = "error.lastname.length")
private String strLastName = "";
谢谢
推荐答案
为了使它在我的情况下有效,需要以下内容:
The following was required in order to make it work in my case:
首先,在我的Java Config类(在我的情况下为WebAppContext.java)中定义LocalValidatorFactoryBean.
First, define a LocalValidatorFactoryBean in my Java Config class (WebAppContext.java in my case).
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
String[] baseNames = {
"resources.messages.layout.LayoutResources",
"resources.messages.layout.MenuResources",
"resources.messages.option.AppConfigResources",
"resources.messages.global.GlobalResources",
"resources.messages.contact.ContactResources",
"resources.messages.currentsession.CurrentSessionResources",
"resources.messages.welcome.WelcomeResources",
"resources.messages.user.UserResources",
"resources.messages.role.RoleResources",
"resources.messages.profile.ProfileResources"
};
messageSource.setCacheSeconds(60);
messageSource.setFallbackToSystemLocale(false);
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
messageSource.setBasenames(baseNames);
return messageSource;
}
@Bean
public LocalValidatorFactoryBean jsr303Validator() {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(this.messageSource());
return localValidatorFactoryBean;
}
然后,在我的控制器中,我像这样自动连接验证器:
Then, in my controller, I autowire that validator like so:
@Autowired
private Validator jsr303Validator;
然后,我发现执行我的JSR-303的唯一方法是手动启动它们,就像这样:
And then, the only way I have found to get my JSR-303 executed is to launch them by hand, like so:
@RequestMapping(value = "/update", method = RequestMethod.POST)
public String processUpdate(@ModelAttribute UserForm userForm,
BindingResult result,
RedirectAttributes redirectAttributes,
SessionStatus status) throws CheckedPersistenceException {
this.userFormValidator.validate(userForm, result);
if (!result.hasErrors()) {
this.jsr303Validator.validate(userForm, result);
}
if(result.hasErrors()) {
return this.UPDATE_VIEW;
}
...
}
这篇关于通过使用@Valid注释无法本地检测到JSR-303错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!