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);
}
}
感谢您的回复。那么DTO的原因是域(hibernate)对象相当复杂,有很多关系,方法等等。这里的用户示例仅用于说明。这就是为什么我想屏蔽来自域的表示层。在这种情况下,我需要执行上述验证,因为我不想公开实体。 我已经计划使用Validator,尽管这会将验证逻辑放在Web层上,这似乎对我来说可疑。除非验证人不仅应该进行简单的现场检查? – arrages 2010-04-14 14:41:09
@arrages Validator被设计用来执行简单的验证。像isInteger,isNotBlank,isNotNull,没有别的。在使用复杂验证时,您最好将其放入您的业务逻辑中。请注意,如你自己所说,我还用很多关系和方法来完成复杂的工作,没有任何问题。 – 2010-04-14 15:00:19