2013-02-01 101 views
1

我發現了一些奇怪的結合問題與Spring MVC的3Spring MVC中綁定額外的對象

我的控制器請求映射是這樣的:

@RequestMapping 
public String save(HttpServletRequest req, 
      @ModelAttribute("userEditForm") UserEditForm form, 
      BindingResult formBindingResult, 
      ModelMap model, 
      @ModelAttribute("session") AdminSession session) { 
    // some validation etc 
} 

UserEditForm

public class UserEditForm { 
    private User user; 
    public User getUser() { ... } 
    public void setUser(User user) { ... } 
} 

AdminSession

public class AdminSession { 
    private User user; 
    public User getUser() { ... } 
    public void setUser() { ...} 
} 

發生了什麼事情是,當我提交表單時,Spring將綁定User,如我在我的UserEditForm對象中預期的那樣,但是,AdminSession也具有受Spring約束的User,因爲它的屬性值也被更新。

我打算假設它是由於在@ModelAttribute對象中都有user屬性。

我認爲在方法簽名中使用UserEditForm表單後的BindingResult會阻止它嗎?對象是獨立的情況下,我的表單元素引用UserEditForm對象:

<@spring.bind "userEditForm.user.name" /> 

<input name="${spring.status.expression}" /> 

我注意到,在生成的HTML它的輸出:

<input name="user.name" /> 

硬編碼名稱爲userEditForm.user.name給我的錯誤,所以這不是前進的方向。

無論如何阻止這種情況發生?

+0

如果你要硬編碼的名字,我想你必須做一個完全合格的名稱,從模型屬性名稱開始。所以,在你的例子中,我期望 CodeChimp

回答

1

這是在使用@ModelAttribute註解處理程序方法參數時的默認行爲。 Spring獲取請求屬性並將它們與@ModelAttribute註釋的對象的屬性相匹配。這就是Spring在決定做什麼時注意的:註釋。

由於兩個UserEditFormAdminSession被註解爲@ModelAttribute,並都有一個User屬性,名爲user.name請求屬性將獲取綁定到兩個User性能。

您試圖在輸入名稱中包含命令名並出現錯誤。這是因爲當發生綁定時,它發生在您的命令對象上,並且Spring在它上面查找屬性(bindinf路徑與命令對象相關),當然表達式不會找到具有該名稱的任何屬性。如果你要使用全名,你可以包裝形式在另一個對象,並使用你的命令來代替,這樣的事情:

public class UserEditFormWrapper { 
    private UserEditForm form; 
    public UserEditForm getForm() { 
     return form; 
    } 
    public void setForm(UserEditForm form) { 
     this.form = form; 
    } 
} 

現在你可以在你的投入使用這樣的表達式:form.user.name當您提交到您的處理方法,現在看起來是這樣的:

@RequestMapping 
public String save(HttpServletRequest req, 
     @ModelAttribute("userEditForm") UserEditFormWrapper formWrapper, 
     BindingResult formBindingResult, 
     ModelMap model, 
     @ModelAttribute("session") AdminSession session) { 

    UserEditForm form = formWrapper.getForm(); 
    // some validation etc 
} 

因爲AdminSession不會被觸發沒有form屬性的綁定。

這是解決這個問題的方法之一,但它有點破解。您不希望將請求參數綁定到AdminSession,但這是您模型的一部分,因此您必須將它創建到某個位置並將其放置在模型上,對嗎?如果是這樣,那麼從方法的參數將其刪除,並從模型中只得到它,像:

@RequestMapping(value = "/test", method = { RequestMethod.POST }) 
public String handlePost(HttpServletRequest req, 
     @ModelAttribute("userEditForm") UserEditForm form, 
     BindingResult formBindingResult, ModelMap model) { 

    AdminSession session = (AdminSession) model.get("session"); 
    // some validation etc 
} 
+0

感謝波格丹,我想知道這是否會是答案。很好的解釋,現在對我來說都很有意義! – Sabooji