Ale*_*eld 8 java validation spring spring-mvc
在使用Spring MVC验证器执行"浅"用户输入验证后,是否有一些使用Spring MVC呈现服务层验证错误的良好实践?例如,拥有以下代码:
@Autowired
private UserService userService;
@RequestMapping(value = "user/new", method = RequestMethod.POST)
public String createNewUser(@ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model){
UserFormValidator validator = new UserFormValidator(); //extending org.springframework.validation.Validator
validator.validate(userForm, result);
if(result.hasErrors()){
model.addAttribute("userForm", userForm);
return "user/new";
}
// here, for example, the user already might exist
userService.createUser(userForm.getName(), userForm.getPassword());
return "redirect:user/home";
}
Run Code Online (Sandbox Code Playgroud)
虽然将此代码作为示例似乎微不足道,但在服务层验证是一项复杂的任务时,对我来说似乎是一个微妙的故事.尽管是一个荒谬的场景,UserService可能会创建一个用户列表,如果其中一个已经存在,那么必须以某种方式通知视图层哪些用户无效(例如已经存在).
我正在寻找一个如何设计一段代码的良好实践,这使得它成为可能
1)处理具有复杂数据作为输入的服务层的验证错误,和
2)向用户呈现这些验证错误
尽可能简单.有什么建议?
选择通常是异常与错误代码(或响应代码),但最佳实践,至少是Bloch,只是在特殊情况下使用异常,这在这种情况下会使他们失去资格,因为用户选择的现有用户名不是闻所未闻.
服务调用中的问题是您假设createUser是一个没有返回值的命令式命令.您应该将其视为"尝试创建用户,并给我一个结果".那么结果可能就是
UserOperationResult枚举的更具体的常量(更好的主意,因为您可能希望USER_ALREADY_EXISTS在创建新用户时和尝试修改用户时返回)UserCreationResult对这个调用完全自定义的对象(不是一个好主意,因为你会爆炸这些)Result<T>或UserOperationResult<T>包装器对象,它组合了一个响应代码常量(ResultCode或UserOperationResultCode分别)和一个返回值T,或者?没有返回值时的通配符......只需要注意不期望包装器的切入点等未经检查的例外之处在于它们避免了所有这些废话,但它们带有一系列问题.我个人坚持最后一个选项,并且过去曾经有过不错的运气.
抛出异常/返回错误代码的替代方法是将to传递Errors 给userService.createUser().然后可以在服务级别执行重复的用户名检查 - 并附加任何错误Errors.这将确保所有错误(浅的和更复杂的)都可以被收集起来并同时呈现给视图.
所以你可以稍微修改你的控制器方法:
@RequestMapping(value = "user/new", method = RequestMethod.POST)
public String createNewUser(@ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model){
UserFormValidator validator = new UserFormValidator();
validator.validate(userForm, result);
// Pass the BindingResult (which extends Errors) to the service layer call
userService.createUser(userForm.getName(), userForm.getPassword(), result);
if(result.hasErrors()){
model.addAttribute("userForm", userForm);
return "user/new";
}
return "redirect:user/home";
}
Run Code Online (Sandbox Code Playgroud)
然后你UserServiceImpl会检查重复的用户本身 - 例如:
public void createUser(String name, String password, Errors errors) {
// Check for a duplicate user
if (userDao.findByName(name) != null) {
errors.rejectValue("name", "error.duplicate", new String[] {name}, null);
}
// Create the user if no duplicate found
if (!errors.hasErrors()) {
userDao.createUser(name, password);
}
}
Run Code Online (Sandbox Code Playgroud)
该Errors班是Spring的验证框架的一部分-所以虽然会有Spring的依赖关系,服务层不会有任何网络相关的代码的任何依赖.
| 归档时间: |
|
| 查看次数: |
7182 次 |
| 最近记录: |