2012-03-20 38 views
3

我有一個Spring 2.x控制器,它擴展了SimpleFormController,從Spring3開始已經棄用了,並且支持帶註釋的控制器。所以我試圖將其轉換爲使用@Controller@InitBinder@Valid進行表單驗證。但是,我無法找到使用Spring 3.x控制器使用多個驗證器的方法。我該怎麼做呢?有沒有辦法在Spring 3註釋的控制器上使用多個Validator?

這裏是我的控制器的豆高清目前的樣子:

<bean name="/s/account" class="mywork.AccountSettingsController" 
    p:formView="forms/account" 
    p:successView="redirect:/app/s/account" 
    p:commandName="accountSettingsForm"> 
    <property name="validators"> 
     <list> 
      <ref bean="emailFormatValidator" /> 
      <ref bean="uniqueEmailValidator" /> 
      <ref bean="changeEmailValidator" /> 
      <ref bean="passwordWithConfirmationValidator" /> 
      <ref bean="changePasswordValidator" /> 
     </list> 
    </property> 
</bean> 

這是一個網頁,它可以讓用戶改變他們的電子郵件地址和密碼控制器。驗證器bean是遺留代碼,但我猜測它們被分割成單獨的類以獲得更好的可重用性。

我想所有這一切進入控制器類本身,使用註釋:

@Controller 
@Secured({BaseController.ROLE_LOGGED_IN}) 
@RequestMapping("/s/account") 
public class AccountSettingsController extends BaseController { 
    private static final String FORM_URL = "/forms/account"; 
    private static final String FORM_NAME = "accountSettingsForm"; 

    @InitBinder(FORM_NAME) 
    public void initBinder(WebDataBinder binder) { 
     // TODO: how to inject > 1 validator for the form? 
     binder.setValidator(...); 
    } 

    @RequestMapping(method = RequestMethod.GET) 
    public ModelAndView get() { 
     ChangePasswordOrEmailForm form = new ChangePasswordOrEmailForm(); 
     ... 
     return new ModelAndView(FORM_URL, FORM_NAME, form); 
    } 
    ... 
} 

至於我可以告訴大家,春季3假設之間存在1對1的關係:控制器 - 外形WebDataBinder-驗證。我可以創建一個綜合驗證器來彙總5個單獨的驗證器bean,並將Validator#supports()Validator#validate()調用委託給它們,但這真的是最好的解決方案嗎?

回答

0

我能想到的最佳解決方案是注入驗證程序集合,並手動通過它們自己旋轉。所以現在我刪除initBinder()從我的控制器類,這裏就是我說:

private List<Validator> accountSettingsValidators; 

// Maps & Collections can't be @Autowired (by type OR name), so use the JSR 250 @Resource annotation to autowire by name 
@Resource 
public void setAccountSettingsValidators(List<Validator> accountSettingsValidators) { 
    this.accountSettingsValidators = accountSettingsValidators; 
} 

@RequestMapping(method = RequestMethod.POST) 
protected ModelAndView processSubmit(HttpServletRequest request, 
            @ModelAttribute(FORM_NAME) ChangePasswordOrEmailForm form, 
            BindingResult bindingResult) { 
    for (Validator validator : this.accountSettingsValidators) { 
     ValidationUtils.invokeValidator(validator, form, bindingResult); 
    } 

    if (bindingResult.hasErrors()) { 
     return new ModelAndView(FORM_URL, FORM_NAME, form); 
    } 

    // process validated form 
} 

在我formControllers.xml Spring配置中,我創建驗證列表中注入:

<util:list id="accountSettingsValidators"> 
    <ref bean="emailFormatValidator" /> 
    <ref bean="uniqueEmailValidator" /> 
    <ref bean="changeEmailValidator" /> 
    <ref bean="passwordWithConfirmationValidator" /> 
    <ref bean="changePasswordValidator" /> 
</util:list> 
3

另一個,我想應該有一個ValidatorFacade,它依次調用所有其他驗證器,這樣你不需要注入,而是將ValidatorFacade附加到前面的initBinder和@Valid中,表單bean將自動調用ValidatorFacade並自動處理所有事情。只是一個想法。

+0

你的意思是[this](https://github.com/hdiv/hdiv/wiki/Appendix-B%3A-Composite-validator-example-for-Spring-MVC)?我實際上在網上找到了幾個不同的例子,所以我想這就是我要去的方式。 – 2012-03-21 20:35:52

+0

是的..我更喜歡使用Spring的autowire而不是xml注入其他驗證器,但是這個想法是一樣的。 – raddykrish 2012-03-21 20:50:45

相關問題