我有一个似乎是spring-mvc中的常见问题。我的几个域对象都有不可更新的字段,因此在我看来,我没有绑定这些字段。 为了竞争起见从视图中排除这些的方式是编辑spring-roo scaffolded视图,将参数的render属性设置为false。
当spring-mvc创建对象的新实例而不是更新现有对象时,这些字段为空。但这意味着对象在控件到达控制器之前未通过验证。
我的很多实体在视图中都会有额外的字段不可更新所以我希望能够提出一个通用的解决方案,而不是继续做同样的工作。再次(违反DRY)。
如果从视图中省略字段,如何允许以一致的方式进行验证?
@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String UserController.update(@Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
populateEditForm(uiModel, user);
return "admin/users/update";
}
uiModel.asMap().clear();
user.merge();
return "redirect:/admin/users/" + encodeUrlPathSegment(user.getId().toString(), httpServletRequest);
}
可能的解决方案:
赞成
缺点
示例:
@InitBinder
public void initBinder(WebDataBinder binder, HttpServletRequest request) {
if (request.getMethod().equals("PUT")) {
binder.setDisallowedFields("registrationDate", "password");
Validator validator = binder.getValidator();
Validator userUpdateValidator = new UserUpdateValidator();
binder.setValidator(userUpdateValidator);
}
}
赞成
缺点
会考虑是否?
不是选项这意味着在保存之前对对象没有验证。更糟糕的是我认为它会影响为数据库生成的DDL,从数据库本身中删除约束。 为了完整起见,只放在这里
此解决方案的想法是在更新之前查找现有域对象。将任何非空字段从请求复制到旧对象。 的优点 - 验证可以通过正常循环。 - 验证不需要根据您所暗示的方法进行更改。
缺点
我想知道如何实现委托给标准JSR-303验证器的验证器,或者如何在修改它之前查找对象。或者,如果有人有任何其他可能的解决方案?
这些解决方案中的任何一种都允许治疗在多个对象上保持一致。
希望要么允许添加注释,例如。 @RooCreateOnly意味着可以对域对象进行注释,将所有验证定义留在一个位置。
答案 0 :(得分:2)
使用@ModelAttribute
注释可以实现最后一个选项。
创建一个返回域对象并向其添加@ModelAttribute
注释的方法。然后将相同的注释添加到要使用该对象的方法的域对象参数中。 Spring将首先从ModelAttribute
方法加载对象,然后将其与发布的数据合并。
示例:
@ModelAttribute("foobar")
public User fetchUser() {
return loadUser();
}
@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String update(@ModelAttribute("foobar") @Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
return etc();
}
答案 1 :(得分:1)
您可以在disabled
文件中使用jspx
属性作为输入标记,其中包含您要标记为只读字段的表单。
另外,请确保清除与该字段相关的z
属性,以便Roo在稍后对该实体进行任何更改时将忽略该标记。
干杯!
答案 2 :(得分:1)
我发布的另一个答案完全与我之前的答案无关。
还有另一种解决方案:将您的域对象包装到只显示您要验证的字段的特殊表单对象中。
示例:
public class UserForm {
private final User user = new User();
// User has many fields, but here we only want lastName
@NotEmpty // Or whatever validation you want
public String getLastName() {
return this.user.getLastName();
}
public void setLastName(String lastName) {
this.user.setLastName(lastName);
}
public User getUser() {
return this.user;
}
}