1

我想使用自定义 Spring 验证我的 MyAccount 表单Validator

基本的验证规则没有问题。

我现在有这个要求,这似乎很明显和普遍:

如果用户(当前登录)更改了他的用户名,我将不得不检查它是否已经在使用中。如果它没有被更改,我很好(它肯定会在检查时使用,这就是为什么我不想在这种情况下检查它)。问题是,验证器是 Spring 管理的 Singleton,我似乎无法访问当前会话(我在其中存储登录上下文 - 即不是 Spring Security)。但我需要当前登录的用户,以便将其电子邮件与表单中输入的电子邮件进行比较。

这是我的场景,但问题实际上是关于如何使用用户会话中的对象进行验证。

我正在考虑解决这个问题的方法:

  1. 仅在 中进行基本验证,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
           }
        }
    
  2. Validator像这样添加第二个验证方法

    public void validateWithCurrentCustomer(Customer current) {
      ...
    }
    

    并使用适当的对象从控制器显式调用它。好不了多少,但至少验证逻辑在一个类中,虽然分为两种方法,其中一种方法不标准。

  3. 没有ValidatorSpring 托管(单例)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 上找不到任何模式。

感谢您的提示。

4

1 回答 1

0

您可以尝试从您的验证器访问任何 Spring bean。也许这个答案可以提供帮助。 我应该在哪里放置需要访问数据库的验证代码?

基本上,您可以创建一个 SpringBeanUtil 单例,它可以让您访问任何您想要的 bean。

于 2013-09-17T14:12:01.340 回答