2012-12-22 43 views
5

當僅顯示Spring MVC模型bean的一部分時,是否有一種方法只在模型中更新從瀏覽器返回的內容?Spring MVC + Hibernate:從瀏覽器中更新部分模型

比方說,我們有一個用戶類(公共屬性只有在這個例子中,當然):

public class User { 
    public String firstName; 
    public String lastName; 
    public String email; 
    public Date subscriptionExpiration; 
} 

現在我作爲一個JSP輸入字段顯示前三個屬性和要更新的對象相應的數據庫。只有這3個參數應該更新,而不是第四個參數。一種方法來完成這將是

@RequestMapping("/user/{userId}", method=RequestMethod.POST) 
public String saveChanges(@PathVariable userId, User user, Model model) { 
    User oldUser = User.loadFromDB(userId); 
    oldUser.firstName = user.firstName; 
    oldUser.lastName = user.lastName; 
    oldUser.email = user.email; 
    oldUser.saveToDB(); 

    model.addAttribute("user", oldUser); 
} 

但這將意味着硬編碼的所有屬性可能會改變,我不喜歡太多。

有什麼方法可以根據用戶允許更改來確定要更新的字段嗎?該機制應該比只假設請求參數中的所有內容都可以更改更明智,否則任何精明的用戶都可以手動將其他字段注入到請求中。

使用@Entity(dynamicUpdate = true)不能解決我眼中的問題,因爲我沒有將整個User對象返回到請求中,並且這樣做會打開很多安全漏洞。

我錯過了一個很好的功能在春天還是有任何其他方式來概念上解決這個問題?任何提示都非常感謝!

回答

3

請參閱this question瞭解如何使用@InitBinder來允許/阻止某些模型字段被Spring綁定以請求參數。這可以確保subscriptionExpiration無法通過注入請求參數進行修改。

而且請參閱the documentation瞭解如何在方法和方法參數上使用@ModelAttribute註釋,以在調用@RequestMapping方法之前從數據庫加載用戶並將其添加到模型,並使用請求參數填充此用戶當@RequestMapping方法被調用時。這允許從DB獲取用戶,並讓Spring使用來自請求的ne值填充它。您所要做的就是驗證用戶的新狀態並將其保存到數據庫中。

2

我覺得方法

BeanUtils.copyProperties(Object source, Object target, String[] ignoreProperties) 

你想要做什麼。它將所有屬性從一個對象複製到另一個對象,而不觸及String[] ignoreProperties中定義的屬性。

將給定源bean的屬性值複製到給定的目標bean中,忽略給定的「ignoreProperties」。

注意:只要屬性匹配,源類和目標類就不必匹配,甚至不必相互派生。源bean公開的但是目標bean不會被忽略的任何bean屬性。

這只是一種方便的方法。對於更復雜的傳輸需求,請考慮使用完整的BeanWrapper。

API Documentation

+0

我暫時做了這樣的事情;我在字段上使用自定義註釋來引導它們是否被更新,然後解析它們以得到一個ignoreProperties列表。它運作良好,但我想避免手動定義。感謝您的輸入! – usimon

0

可以首先從數據庫中讀取的對象並結合則該請求。你可以在FuWeSta-Sample找到一個例子。

它使用必須由Spring初始化的helper-bean

0

一種選擇是利用表單中的隱藏字段。一個選項與退後,但它適用於某些情況下

0

您正在尋找的不錯的功能是@ModelAttribute。我假設你的表單也會發布用戶ID。

public class UserController { 

    @ModelAttribute 
    public User getUser(@RequestParam(value = "id", required = false) Long id) { 
     return User.loadFromDB(id); 
    } 

    @RequestMapping("/user/{id}", method=RequestMethod.POST) 
    public String saveChanges(@ModelAttribute User user, BindingResult bindingResult, Model model) { 

     if (bindingResult.hasErrors()) { 
      // return ... 
     } 

     // model.asMap().clear(); 

     user.saveToDB(); 
     // return ... 
    } 
}