Является ли отражение моим лучшим вариантом здесь? - PullRequest
2 голосов
/ 14 сентября 2011

Мы разрешаем пользователям устанавливать некоторые настройки в нашем веб-приложении. Когда они входят в определенные сайты, им разрешается делать / видеть разные экраны по сравнению с тем, когда они находятся на другом сайте. Одним из наших требований является то, что мы скрываем настройки на странице, к которой они не могут получить доступ на текущем вошедшем в систему сайте. В настоящее время мы используем Spring MVC для обработки этих запросов.

Вот упрощенный пример нашего POJO:

public class Preferences {
  boolean prefA; //Valid when can do A
  String prefB;  //Valid when can do B
  Integer prefC; //Valid when can do C
  ....
  Long prefZ;    //Valid when can do Z
}

Вот код контроллера:

@RequestMapping(method = RequestMethod.POST, value = "preferences.xhtml")
public ModelAndView updateRequestPreferences(@ModelAttribute(USER_PREFERENCES) final Preference preferences, final BindingResult results)
{
  return updatePreferences(preferences, results);
}

В настоящее время updatePreferences выполняет отражение и гарантирует, что значение не будет нулевым, прежде чем оно сохранит входные настройки. Это связано с тем, что Spring MVC создает новый экземпляр Preferences и затем заполняет значения тем, что было в пользовательском интерфейсе.

Мы могли бы сделать следующее в установщике предпочтений:

public void setPreferences(Preferences preferences) {
  if (preferences.getPrefA() != null) {
    this.preferences.setPrefA(preferences.getPrefA());
  }
  if (preferences.getPrefB() != null) {
    this.preferences.setPrefB(preferences.getPrefB());
  } 
  ...
  if (preferences.getPrefZ() != null) {
    this.preferences.setPrefZ(preferences.getPrefZ());
  }
}

Это было бы громоздко даже с помощью вспомогательной функции для всех проверок в методе сеттера (и кажется простым шагом, чтобы забыть, когда создается новое предпочтение); в то же время рефлексия кажется копом. Есть ли лучший способ реорганизовать это?

1 Ответ

1 голос
/ 14 сентября 2011

Вы можете настроить Spring MVC для заполнения полей ранее существовавшего объекта, а не для создания нового.

Например, вы можете использовать @SessionAttributes(USER_PREFERENCES) для хранения экземпляра Preferences всеанс между визуализацией формы и обработкой ее отправки.

Другой подход заключается в загрузке нового экземпляра Preferences из базы данных в качестве неявного атрибута модели:

@ModelAttribute(USER_PREFERENCES)
public Preferences loadPreferences(@RequestParam("key") String key) {
    return loadPreferencesByKey(key);
}

Обратите внимание, что во всех случаях(и ваш первоначальный подход также нуждается в этом), вам нужно указать набор разрешенных полей в методе @InitBinder, чтобы предотвратить изменение злоумышленником полей, которые не были отображены в форме:

@InitBinder(USER_PREFERENCES)
public void initBinder(WebDataBinder b) {
    b.setAllowedFields("prefA", "prefB");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...