2012-04-06 51 views
0

我在Spring中處理表單支持對象的方式很困難。如預期的那樣,在html表單中具有相應輸入標籤的ScreenObject屬性在帖子中存活。但是,如果某個媒體資源沒有輸入標記,則會發生兩種情況:彈簧表單支持對象問題

  1. 如果將屬性作爲請求參數傳入,則它會在帖子後生存。
  2. 如果屬性沒有作爲請求參數傳遞,它不會在帖子中生存。

這是我的代碼。

畫面目標

private Integer hostSiteSectionId; // no input tag but survives if passed as a request param 
private String name; // input tag so survives 
private String orderFactor; // input tag so survives 

private Integer hostSiteId; // no input tag but survives if passed as a request param 
private String hostSiteName; // no input tag and not passed as request param so does not survive 

GET

@RequestMapping(method=RequestMethod.GET) 
public ModelAndView edit(@RequestParam(value="hostSiteId", required=false) Integer hostSiteId, @RequestParam(value="hostSiteSectionId", required=false) Integer hostSiteSectionId, Locale locale) { 
    HostSiteSectionHeaderEditScreenObject screenObject=new HostSiteSectionHeaderEditScreenObject(); 

    initializeScreenObject(hostSiteId, hostSiteSectionId, screenObject, locale, true); 

    ModelAndView modelAndView=new ModelAndView(); 
    modelAndView.addObject("screenObject", screenObject); 
    modelAndView.setViewName(WebView.HOST_SITE_SECTION_HEADER_EDIT_PAGE.getViewName()); 
    return modelAndView;  
} 

POST與取消

@RequestMapping(method=RequestMethod.POST, params="cancel") 
public String cancel(@ModelAttribute("screenObject") HostSiteSectionHeaderEditScreenObject screenObject) { 
    // logic that returns redirect 
} 

我的初始化ScreenObject()方法只設置screenObject的屬性。它不在模型上運行。我不明白它會干擾什麼,所以我不會發布它的基本代碼。

在這篇文章中,和它的作品在其他職位一樣,screenObject有以下幾點:

  1. 通過輸入標籤的形式由用戶提供的輸入都將存在。沒有任何問題。
  2. hostSiteId(沒有輸入標籤)存在於screenObject僅當吸氣URL包含它作爲參數(編輯?hostSiteId = 2例如)僅當包含吸氣劑的url
  3. hostSiteSectionId(沒有輸入標籤)存在於screenObject它作爲參數(編輯?hostSiteSectionId = 2例如)
  4. 所有其他屬性沒有相應的輸入標記,並且不作爲請求參數傳遞爲null。

爲了進一步說明#4。我有一個在initializeScreenObject()方法中設置的screenObject.hostSiteName屬性。該視圖正確地使用<td>${screenObject.getHostSiteName()}</td>進行了渲染。現在我點擊取消提交控制。當控制器接管提交時,該屬性爲空。

請解釋這是否是預期的。如果預計,請解釋如何解決它。我想,我可以爲那些需要在帖子後面生存的屬性添加隱藏的表單字段,但這有點破解。我希望有更好的答案。原始請求參數如何在後期操作中進入焦點?

回答

1

這聽起來像預期的行爲。作爲POST處理程序方法的參數傳遞的HostSiteSectionHeaderEditScreenObject實例與您在GET處理程序方法中放入模型中的實例不同。默認情況下,它是Spring創建的一個新實例。 Spring會根據POST請求中存在的參數將值綁定到對象的字段。所以如果一個參數在POST中不存在(例如,因爲你沒有在它的HTML表單中輸入一個輸入),這個字段將不會被Spring設置,它將只是該字段的默認初始值。

聽起來好像你想要的是將initializeScreenObject()應用到屏幕對象,然後在請求參數值之後應用?有幾種方法可以解決這個問題。一會是有@ModelAttribute註解控制器方法:

@ModelAttribute("screenObject") 
public HostSiteSectionHeaderEditScreenObject initScreenObject(@RequestParam(value="hostSiteId", required=false) Integer hostSiteId, @RequestParam(value="hostSiteSectionId", required=false) Integer hostSiteSectionId, Locale locale) { 
    HostSiteSectionHeaderEditScreenObject screenObject=new HostSiteSectionHeaderEditScreenObject(); 

    initializeScreenObject(hostSiteId, hostSiteSectionId, screenObject, locale, true); 
} 

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-methods

如果你這樣做,你的GET處理方法可以簡化爲只返回一個視圖名稱。

+0

我有一種感覺,這也是預期的行爲。但是從我一直在閱讀的關於Spring的文章中很難簡單地接受它。鑑於Spring顯然建議直接使用域對象作爲模型,這將很快導致數據丟失。拋開Web的那些愚蠢的例子。實際應用程序中的典型域對象不會在單個表單中編輯其所有屬性。因此,如果我們採用域對象,將其用作模型屬性,然後將其在發佈中發送併發送給服務以進行保存,我們將對結果感到非常驚訝。 – jacekn 2012-04-06 20:35:12

+1

這並不是我碰到的問題。我最習慣的是從數據庫加載的域對象(例如,在@ModelAttribute註釋的方法中),然後Spring將請求參數值綁定到對象的字段。如果沒有字段的請求參數,則該字段的值不會更改。因此,當您更新數據庫中的記錄時,對於未根據請求參數值設置的字段,沒有數據「丟失」。 – sdouglass 2012-04-06 21:54:32