[英]Data binding of an abstract class in spring-mvc
我已經通過Spring文檔和源代碼,仍然沒有找到我的問題的答案。
我在我的域模型中有這些類,並希望在spring-mvc中將它們用作后備表單對象。
public abstract class Credentials {
private Long id;
....
}
public class UserPasswordCredentials extends Credentials {
private String username;
private String password;
....
}
public class UserAccount {
private Long id;
private String name;
private Credentials credentials;
....
}
我的控制器:
@Controller
public class UserAccountController
{
@RequestMapping(value = "/saveAccount", method = RequestMethod.POST)
public @ResponseBody Long saveAccount(@Valid UserAccount account)
{
//persist in DB
return account.id;
}
@RequestMapping(value = "/listAccounts", method = RequestMethod.GET)
public String listAccounts()
{
//get all accounts from DB
return "views/list_accounts";
}
....
}
在UI上,我有不同憑據類型的動態表單。 我的POST請求通常如下所示:
name name
credentials_type user_name
credentials.password password
credentials.username username
如果我嘗試向服務器提交請求,則拋出以下異常:
org.springframework.beans.NullValueInNestedPathException: Invalid property 'credentials' of bean class [*.*.domain.UserAccount]: Could not instantiate property type [*.*.domain.Credentials] to auto-grow nested property path: java.lang.InstantiationException
org.springframework.beans.BeanWrapperImpl.newValue(BeanWrapperImpl.java:628)
我最初的想法是使用@ModelAttribute
@ModelAttribute
public PublisherAccount prepareUserAccountBean(@RequestParam("credentials_type") String credentialsType){
UserAccount userAccount = new PublisherAccount();
Class credClass = //figure out correct credentials class;
userAccount.setCredentials(BeanUtils.instantiate(credClass));
return userAccount;
}
這種方法的問題在於,在任何其他方法(如listAccounts
)之前調用prepareUserAccountBean
方法也是不合適的。
一個強大的解決方案是將prepareUserAccountBean
和saveUserAccount
到單獨的Controller。 聽起來不對:我希望所有與用戶相關的操作都駐留在同一個控制器類中。
有什么簡單的解決 我可以以某種方式利用DataBinder,PropertyEditor或WebArgumentResolver嗎?
謝謝!!!!!
我看不到任何簡單而優雅的解決方案。 也許是因為問題不是如何在Spring MVC中綁定抽象類的數據,而是:為什么首先在表單對象中使用抽象類? 我想你不應該。
從表單發送到控制器的對象稱為“表單(支持)對象”,原因如下:對象屬性應反映表單字段。 如果您的表單包含用戶名和密碼字段,那么您的類中應該有用戶名和密碼屬性。
因此credentials
應具有UserPasswordCredentials
類型。 這將跳過您的“抽象實例化嘗試”錯誤。 兩個解決方案:
我不確定,但您應該在控制器上使用ViewModel類而不是Domain Objects。 然后,在saveAccount方法中,您將驗證此ViewModel,如果一切正常,您將其映射到您的域模型並保留它。
通過這樣做,你有另一個優勢。 如果您將任何其他屬性添加到您的域UserAccount類,例如: private bool isAdmin 。 如果您的Web用戶向您發送一個帶有isAdmin = true的POST參數,該參數將綁定到用戶域類並保持不變。
嗯,這就是我的方式:
public class NewUserAccount {
private String name;
private String username;
private String password;
}
@RequestMapping(value = "/saveAccount", method = RequestMethod.POST)
public @ResponseBody Long saveAccount(@Valid NewUserAccount account)
{
//...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.