Spring MVC的:在哪里放置验证,以及如何验证实体引用

问题描述:

比方说,我有以下命令bean创建用户:在表格上Spring MVC的:在哪里放置验证,以及如何验证实体引用

public class CreateUserCommand { 

    private String userName; 
    private String email; 

    private Integer occupationId; 
    pirvate Integer countryId; 

} 

occupationId和countryId被下拉选择的值。他们映射到数据库中的一个实体(职业,国家)。

该命令对象将要被馈送到服务外观像这样:

userServiceFacade.createUser(CreateUserCommand命令);

此外观将构造一个用户实体发送到实际服务。所以我想,在外观层,我将不得不做几个dao调用来映射用户实体的所有查找属性。

基于此,验证occupId和countryId映射到真实实体的最佳策略是什么?哪里是执行此验证的最佳位置?有Spring验证器,但我不确定这是否是最好的地方,因为我对此方法很谨慎,因为验证与Web层相关,但这也意味着我需要在验证器中进行dao调用进行验证,但是当命令 - >实体转换发生时,我需要再次在外观层中调用dao's。

有什么我可以做得更好吗?

谢谢。

您确定您需要DTO来检索实体吗?

我想你的用户是显示您的形式是通过使用一些<选择HTML元素,其类似于

<select name="occupation"> 
    <option name="0">A occupaation</option> 
    <option name="1">Other occupaation</option> 
    <option name="2">Another occupaation</option> 
</select> 

弹簧时如下

public class User implements Serializable { 

    private String userName; 
    private String email; 

    private Occupation occupation; 
    private Country country; 

} 

通常,到另一实体的引用使用数据绑定将您选择的HTML元素绑定到您的属性。使用的方法被称为initBind

public class UserController extends BaseCommandController { 

    private OccupationRepository occupationRepository; 
    private CountryRepository countryRepository; 

    // getter's and setter's (retrieved by Dependency Injection supported by Spring) 

    public UserController() { 
     setCommandClass(User.class); 
     setValidator(new UserValidator()); 
    } 

    public void initBind(HttpServletRequest request, ServletRequestDataBinder binder) { 
     binder.registerCustomPropertyEditor(Occupation.class, new PropertyEditorSupport() { 

      public void setAsText(String occupationId) { 
       // StringUtils belongs to jakarta-commons lang 
       if(StringUtils.isBlank(occupationId)) { 
        setValue(null); 

        return; 
       } 

       setValue(occupationRepository.getById(Integer.valueOf(occupationId))); 
      } 

      public String getAsText() { 
       if(getValue() == null) 
        return; 

       return String.valueOf(((Occupation) getValue()).getId()); 
      } 
     }); 

     // Same approach when binding Country 
    } 

} 

通知您可以通过分配的WebBindingInitializer对象

public class UserBindingInitializer implements WebBindingInitializer { 

    private OccupationRepository occupationRepository; 
    private CountryRepository countryRepository; 

    // getter's and setter's (retrieved by Dependency Injection supported by Spring) 

    public void initBinder(WebDataBinder binder, WebRequest request) { 
     binder.registerCustomPropertyEditor(Occupation.class, new PropertyEditorSupport() { 

      public void setAsText(String occupationId) { 
       // StringUtils belongs to jakarta-commons lang 
       if(StringUtils.isBlank(occupationId)) { 
        setValue(null); 

        return; 
       } 

       setValue(occupationRepository.getById(Integer.valueOf(occupationId))); 
      } 

      public String getAsText() { 
       if(getValue() == null) 
        return; 

       return String.valueOf(((Occupation) getValue()).getId()); 
      } 
     }); 
    } 

} 

更换 initBind方法...

public class UserController extends BaseCommandController { 

    private OccupationRepository occupationRepository; 
    private CountryRepository countryRepository; 

    // getter's and setter's (retrieved by Dependency Injection supported by Spring) 

    public void setUserBindingInitializer(UserBindingInitializer bindingInitializer) { 
     setWebBindingInitializer(bindingInitializer); 
    } 

而且你UserValidator(注意:您的验证不知道任何关于任何存储库的其他信息)

public class UserValidator implements Validator { 

    public boolean supports(Class clazz) { 
     return clazz.isAssignableFrom(User.class); 
    } 

    public void validate(Object command, Errors errors) { 
     User user = (User) command; 

     if(user.getOccupation() == null) 
      errors.rejectValue("occupation", "errors.required", null); 

     if(user.getCountry() == null) 
      errors.rejectValue("country", "errors.required", null); 
    } 

} 
+0

感谢您的回复。那么DTO的原因是域(hibernate)对象相当复杂,有很多关系,方法等等。这里的用户示例仅用于说明。这就是为什么我想屏蔽来自域的表示层。在这种情况下,我需要执行上述验证,因为我不想公开实体。 我已经计划使用Validator,尽管这会将验证逻辑放在Web层上,这似乎对我来说可疑。除非验证人不仅应该进行简单的现场检查? – arrages 2010-04-14 14:41:09

+0

@arrages Validator被设计用来执行简单的验证。像isInteger,isNotBlank,isNotNull,没有别的。在使用复杂验证时,您最好将其放入您的业务逻辑中。请注意,如你自己所说,我还用很多关系和方法来完成复杂的工作,没有任何问题。 – 2010-04-14 15:00:19