2012-09-03 136 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;