Привязка данных к абстрактному классу в 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";
  }
  ....
}

В пользовательском интерфейсе у меня есть динамическая форма для различных типов учетных данных. Мой запрос 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;
    }

. Проблема с этим подходом заключается в том, что метод prepareUserAccountBean вызывается раньше любых других методов (например, listAccounts ), которые не подходит.

Одним из надежных решений является перемещение prepareUserAccountBean и saveUserAccount на отдельный контроллер. Это звучит неправильно: я хочу, чтобы все пользовательские операции находились в одном и том же классе контроллеров.

Любое простое решение? Могу ли я каким-либо образом использовать DataBinder, PropertyEditor или WebArgumentResolver?

Спасибо !!!!!

14
задан Jerome Dalbert 9 January 2013 в 10:22
поделиться

1 ответ

Я не уверен, но вы должны использовать классы ViewModel на своих контроллерах вместо объектов домена. Затем внутри вашего метода saveAccount вы должны проверить эту ViewModel, и если все пойдет правильно, вы сопоставите ее со своей моделью предметной области и сохраните ее.

Поступая таким образом, вы получаете еще одно преимущество. Если вы добавите любое другое свойство в свой класс UserAccount домена, например: private bool isAdmin. Если ваш веб-пользователь отправит вам параметр POST с isAdmin=true, который будет привязан к классу домена пользователя и сохранен.

Ну, я бы сделал так:

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)
{
    //...
}
-1
ответ дан 1 December 2019 в 16:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: