我想使用自定义 Spring 验证我的 MyAccount 表单Validator
。
基本的验证规则没有问题。
我现在有这个要求,这似乎很明显和普遍:
如果用户(当前登录)更改了他的用户名,我将不得不检查它是否已经在使用中。如果它没有被更改,我很好(它肯定会在检查时使用,这就是为什么我不想在这种情况下检查它)。问题是,验证器是 Spring 管理的 Singleton,我似乎无法访问当前会话(我在其中存储登录上下文 - 即不是 Spring Security)。但我需要当前登录的用户,以便将其电子邮件与表单中输入的电子邮件进行比较。
这是我的场景,但问题实际上是关于如何使用用户会话中的对象进行验证。
我正在考虑解决这个问题的方法:
仅在 中进行基本验证,
Validator
然后在Controller
. 似乎不是一个好的解决方案。@RequestMapping(value="/myaccount", method=RequestMethod.GET) public String myAccount(@Valid MyAccountForm form, BindingResult result, HttpSession session) { boolean hasUsernameChanged = // check using session if (hasUsernameChanged && CustomerService.customerAlreadyExists(form.getUsername())) result.rejectValue("username", "my.error.code"); if (result.hasErrors()) { // handle errors } else { // proceed } }
Validator
像这样添加第二个验证方法public void validateWithCurrentCustomer(Customer current) { ... }
并使用适当的对象从控制器显式调用它。好不了多少,但至少验证逻辑在一个类中,虽然分为两种方法,其中一种方法不标准。
没有
Validator
Spring 托管(单例)bean,但每次都在 initBinder 方法中创建它。代替:@Autowired public MyAccountController(MyAccountFormValidator validator) { this.validator = validator; } @InitBinder protected void initBinder (WebDataBinder binder) { binder.setValidator(validator); }
做
@InitBinder protected void initBinder (WebDataBinder binder, HttpSession session) { Customer current = ...// get from session binder.setValidator(new MyAccountFormValidator(current)); }
但是这里的问题是,由于验证器不是 Spring 管理的,因此很难将服务(如 CustomerService)注入验证器,以检查电子邮件是否可用。
我错过了什么,还有其他方法可以实现我想要的吗?这似乎是一个常见问题,但我在 Google 或 SO 上找不到任何模式。
感谢您的提示。