Подтвердить что ты не робот

Сохранение данных для сеанса в JSF

Я новичок в мире J (2) разработки EE и веб-приложений, но быстро перемещаю свой путь вокруг и многому учусь. Каждый день - фантастическое путешествие нового открытия для меня.

В настоящее время я работаю над проектом, в котором я использую Visual JSF Woodstock на Glassfish v2. Я также очень новичок в JSF.

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

Точно, как это сделать, моя озабоченность кроется. Я знаю, что в JSP вы можете использовать session.setAttribute("myObj", myObject), который сохранил бы объект на стороне клиента с помощью файлов cookie или перезаписи URL или скрытых переменных формы.

С другой стороны, в JSF я использую Session scoped beans, скажем, SessionBean1, например, и сохраняю объекты как свойства SessionBean1 (например, SessionBean1.setSomeOjb(myObj)). Это правильный путь?

Я предполагаю, что выполнение этого способа приведет к увеличению использования памяти на сервере, так как каждый запрос создаст новый экземпляр сеанса bean, SessionBean1 плюс память, используемую сохраненными экземплярами myObject в SessionBean1.

Я прочитал, что вы можете использовать FacesContext.getExternalContext().getSession/getSessionMap(), который сохранил бы переменные сеанса на стороне клиента.

Итак, какой из методов вы бы предположили, что я использую - область сеанса bean или карту сеанса для сохранения объектов для доступа между запросами на сеанс?

Спасибо.

4b9b3361

Ответ 1

В целом Java EE Web Apps, как правило, не ожидает сохранения клиентских данных сеанса. Вы правы, чтобы беспокоиться о раздувании сеанса на стороне сервера. Общей проблемой является наличие огромных следов сеанса, которые могут вызвать значительные проблемы с ресурсами и производительностью, и могут быть особенно в кластерных средах.

Я хотел бы знать, где вы видите

Я прочитал, что вы можете использовать FacesContext.getExternalContext(). getSession/getSessionMap(), который сохранил бы переменные сеанса на стороне клиента.

Я верю (исправьте меня по этому вопросу), что это просто дает доступ к объекту HttpSession, на котором вы можете затем использовать тот же

 session.setAttribute("myObj", myObject)

это само по себе не возвращает объект клиенту, он хранится на сервере и вводится с помощью некоторого идентификатора сеанса, обычно передаваемого в файл cookie.

Теперь есть два других метода: вы можете явно указать, чтобы данные помещались в куки файлы собственного производства - API-интерфейсы сервлетов, к которым вы можете получить доступ из JSF или JSP, позволят вам это сделать, или вы можете использовать скрытые поля на своем форм и, следовательно, передавать данные сеанса aorund.

Но рассмотрим это. Эмпирическое правило на сервере приложений, которое я использую, заключается в том, что HttpSession порядка 1k-4k обычно не является проблемой. Больше, чем это (и я видел сессии измеренных в мегабайтах), подчеркивают инфраструктуру. Если бы вас беспокоили сеансы такого размера, вы ожидали бы отправить мегабайты данных в файл cookie или скрытое поле обратно в браузер по каждому запросу? Даже 1k-2k, вероятно, немного большой.

Итак, рекомендации:

  • Держите его простым. Используйте Session API или его манифеста JSF.

  • Сохраняйте количество данных в сеансе под контролем.

Добавлено в ответ на вопрос о кластеризации:

Как правило, в кластерной среде мы имеем сродство к сеансу, так что запросы отправляются обратно одному члену кластера. Однако нам все еще нужно рассмотреть случай (возможно, если члены кластера не удаются), когда запрос переходит на другой сервер.

Некоторые поставщики приложений для сервера предлагают репликацию сеанса либо через прямую межсерверную связь, либо путем сохранения сеанса в базе данных - очевидно, что здесь есть накладные расходы, поэтому иногда для сеансов с низким значением мы просто принимаем потерю сеанса в случае отказ.

Существует аргумент, что если данные сеанса имеют высокое значение, то оно должно сохраняться приложением, оно фактически является бизнес-данными и должно рассматриваться как таковое. Для этого все чаще используются базы данных NOSQL, такие как Cloudant или MongoDb. В этом случае мы можем думать о сеансе HTTP как кэш, зная, что данные сеанса могут быть получены в случае ошибки.

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

Итак, следующий принцип:

3). Не перегружайте сеанс HTTP только потому, что он есть. Рассмотрим деловую ценность данных и следует ли ее сохранить.

Ответ 2

Я работаю над проектом университета вместе со своими коллегами, это веб-сайт, подобный GoogleImage Labeler. Итак, у нас есть UserController, с его методами входа в систему, выхода из системы и т.д.... и мы используем этот сеанс следующим образом:

@ManagedBean(name = "userController")
@SessionScoped

Хорошо, это то, что создает для вас мастер NetBeans.

Наш способ создания и управления сеансом:

В методе register (в котором мы используем атрибуты формы в XHTML...) мы сохраняем пользователя в БД, а затем добавляем значения в сеансе:

FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("user", current);

Где "текущий" - Пользователь (конечно, зарегистрированный пользователь). У нас есть тот же метод входа.

В режиме выхода мы имеем:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

Надеюсь, это поможет вам.

Ответ 3

Итак, какой из методов вы бы предположили, что я использую - область сеанса bean или файл сеанса для сохранения объектов для доступа между запросами на сеанс?

Эти две вещи хранят данные точно в одном и том же месте.

<managed-bean>
  <managed-bean-class>foo.Bar</managed-bean-class>
  <managed-bean-name>bar</managed-bean-name>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

После ссылки в выражении вы можете запрограммировать "бар" программно через внешний внешний контекст.

FYI: в JSF2 декларация может быть удалена и заменена аннотациями:

@ManagedBean(name="bar") @SessionScoped
public class Bar {
...