spring mvc嵌套模型validation

我有两个模型: User,Project

 public class Project{ private int id; @NotEmpty(message="Project Name can not be empty") private String name; private User manager; private User operator; //getter/setter omitted } public class User{ private int id; private String name; //omit other properties and getter/setter } 

现在,当我创建一个新项目时,我将向ProjectController提交以下参数:

projects?name=jhon&manager.id=1&operator.id=2...

然后我将创建一个新的Project对象并将其插入到db。

但是我必须validation管理器的id和运算符是否有效,也就是说如果用户表中存在匹配的id,我将validation它。

所以我想知道如何实现这种validation?


update1:​​使用validation器

这是创建新项目的表单:

  Manager:  
Operator:
Name:
@Override public void validate(Object obj, Errors errors) { User user = (User) obj; int id=user.getId(); User u=userDao.query(id); if(u==null){ errors.rejectValue("id", "user does not exist!"); } }

看来这个validation器有效。

但是,错误消息无法在窗体中显示。

然后通过调试我检查结果对象,我发现了这个:

 org.springframework.validation.BeanPropertyBindingResult: 2 errors Field error in object 'project' on field 'id': rejected value [0]; codes [user does not exist!.project.id,user does not exist!.id,user does not exist!.int,user does not exist!]; arguments []; default message [null] Field error in object 'project' on field 'id': rejected value [0]; codes [user does not exist!.project.id,user does not exist!.id,user does not exist!.int,user does not exist!]; arguments []; default message [null] 

似乎结果确实有错误,但它的路径是project.id而在我的表单中它是project.manager.id

怎么修?

这是一种可能的解决方案。

创建以下类:

 ... import org.springframework.validation.Validator; ... @Component public class ProjectValidator implements Validator { @Override public boolean supports(Class clazz) { return Project.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { Project project = (Project) target; /* Do your checks here */ ... if (managerIdDoesNotMatch) { errors.rejectValue("manager.id", "your_error_code"); } ... if (operatorIdDoesNotMatch) { errors.rejectValue("operator.id", "your_error_code"); } ... } } 

在您的控制器中执行以下操作:

 ... public class ProjectController { @Autowired ProjectValidator projectValidator; ... @RequestMapping(...) public String yourCreateMethod(..., @ModelAttribute @Valid Project project, BindingResult result) { projectValidator.validate(project, result); if (result.hasErrors()){ // do something } else { // do something else } } } 

这应该让你开始。 您可以以不同方式实例化/设置validation器,拥有一个用户子validation器,但您可以获得一般的想法。

参考文献:

  • 最新的Springvalidation文档
  • 此Stack Overflowpost介绍了如何执行validation

实际上你需要做的是添加@Valid

 private User manager; private User operator; 

喜欢这个

 @Valid private User manager; @Valid private User operator; 

在Controller中,您可以添加自定义validation器:

 @InitBinder protected void initBinder(WebDataBinder binder) { binder.setValidator(new ProjectValidator()); } 

在此validation器中,您可以检查User对象或委托给UserValidator ,如6.3节前面的最后一段所述

我做了Jerome Dalbert建议的内容,另外添加了一个自定义BeanValidator,用于将validation的实际工作委托给JSR 303实现。

前缀用于表示表单中属性的路径。

 @Component public class BeanValidator implements org.springframework.validation.Validator, InitializingBean { private Validator validator; public void afterPropertiesSet() throws Exception { ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); validator = validatorFactory.usingContext().getValidator(); } public boolean supports(Class clazz) { return true; } public void validate(Object target, Errors errors, String prefix) { Set> constraintViolations = validator.validate(target); for (ConstraintViolation constraintViolation : constraintViolations) { String propertyPath = constraintViolation.getPropertyPath().toString(); String message = constraintViolation.getMessage(); errors.rejectValue(prefix + "." + propertyPath, "", message); } } public void validate(Object target, Errors errors) { validate(target, errors, ""); } } 

在这里我如何在UserValidator中使用它:

 @Component public class UserValidator implements Validator { @Autowired BeanValidator beanValidator; @Override public boolean supports(Class clazz) { return User.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { User user = (User) target; beanValidator.validate(user.getAddress(), errors, "address"); } } 

参考文献: