2012-09-03 141 views
4

我有两个型号:User,ProjectSpring MVC的嵌套模型验证

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对象并将其插入到数据库中。

但是,我必须验证经理和运营商的ID是否有效,也就是说我会验证,如果在用户表中有匹配的ID。

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


UPDATE1:使用验证

这是创建新项目的形式:

<sf:form method="${project.id==0?'post':'put'}" commandName="project" action="${context}${action}"> 
    Manager:<sf:input path="manager.id" /> <sf:errors path="manager.id" /> <br /> 
    Operator:<sf:input path="operator.id" /> <sf:errors path="operator.id" /> <br /> 
    Name:<sf:input path="name" /> <sf:errors path="name" /> <br /> 
    <input type="submit" value="Submit" /> 
</sf:form> 


@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!"); 
    } 
} 

看来,这验证工作。

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

然后虽然调试我检查结果对象,我发现这一点:

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

如何修理?

+0

你如何为你的'Project'进行验证?是否有定制的验证器?你使用JSR-303验证吗? – Pao

+0

没有验证器。我不知道如何做到这一点。 – hguser

+0

[Spring doc on validation](http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/validation.html)应该会给你一个启动 – Pao

回答

3
前的最后一段做 here

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

创建类下面:

... 
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 
     } 
    } 

} 

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

参考文献:

+0

我尝试了下一步。然而,它并不像我预期的那样工作。你能检查我的更新吗?谢谢。 – hguser

+0

'errors.rejectValue(“manager.id”,...)'。我不能尝试这个,因为项目对象容器需要验证的另一个用户实例运算符。 – hguser

+0

那么,一个ProjectValidator应该做的伎俩。另外,只需在控制器中调用一个验证器即可。看看我编辑的答案。 –

1

在你的控制器,你可以添加自定义的验证:

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

在此验证,您可以检查User对象或委托给一个UserValidator,为第6.3

0

我做了什么杰罗姆Dalbert建议,另外增加了一个自定义的BeanValidator委派验证到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<ConstraintViolation<Object>> constraintViolations = validator.validate(target); 
    for (ConstraintViolation<Object> 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"); 
} 
} 

参考文献:

2

其实你需要做的是

添加 @Valid
private User manager; 
private User operator; 

这样

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