2009-08-15 3 views
21

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

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

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

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

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

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

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

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

Спасибо.

+1

«каждый запрос создаст новый экземпляр компонента, обработанного сеансом». ЭТО ПОЛНОСТЬЮ НЕПРАВИЛЬНО –

ответ

21

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

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

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

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

session.setAttribute("myObj", myObject) 

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

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

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

Так рекомендации:

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

  2. Хранить объем данных в сеансе под контролем.

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

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

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

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

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

Таким образом, следующий принцип:

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

+0

Вы правы. Я ошибочно понял, что целые объекты сеанса сохраняются на карте сеанса, и тогда карта сеанса отправляется клиенту, где он хранится в виде файлов cookie или скрытого поля. Вместо этого это идентификатор сеанса, который отправляется клиенту. Если я правильно понял, этот идентификатор сеанса можно использовать для извлечения экземпляра HttpSession, который хранит все атрибуты для данного веб-сеанса, верно? Спасибо, что указали на мое недоразумение. – SibzTer

+0

Привет, я знаю, что вы долго отвечаете на вопрос, но вы сказали что-то интересное о кластеризованной среде. Как сохранить сеанс в этом типе архитектуры, если сеанс сохранен на сервере, который отвечает на запрос? – kavain

+1

@Kavain: Хорошие серверы Java-EE предоставляют возможность оптимизировать репликацию сеанса в кластерах для перехода на другой ресурс. Они позволяют настраивать серверы группами, поэтому не все серверы получают всю информацию о сеансе. Только те, которые находятся в одной группе. Лучше для производительности в самой репликации и в использовании памяти. Так, например, с 1.000.000 пользователями с размером сеанса 100k на 100 серверах не означает, что для каждого сервера потребуется 100 ГБ памяти. Запрошенное в группах по 3, потребует от каждого сервера всего 3 ГБ. И размер сеанса 100k большой ... – Kukeltje

2

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

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

<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> 

После ссылки в выражении, вы можете поиска «бар» программно через external context.

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

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

Должен признаться, что прошло около трех лет с тех пор, как я коснулся JSF. Тогда я просто использовал бы обработанный сеансом управляемый bean-компонент, в значительной степени, как вы показываете. В то время я не рассматривал никаких альтернатив. Я предполагаю, что одна проблема может заключаться в том, чтобы удостовериться, что мы поддерживаем эту опрятность, не хотим постепенно переваривать множество управляемых bean-компонентов с сессионным контролем. Возможно, это зависит от тщательно выбранных имен бобов. – djna

14

Я работаю над проектом университета со своими коллегами, является веб-как GoogleImage Маркировщика. Ну, у нас есть UserController, с его методами входа в систему, выхода из системы и т. Д. ...и мы сфера сессии, как это:

@ManagedBean(name = "userController") 
@SessionScoped 

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

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

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

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

Где «текущий» является пользователь (Вошедший пользователь, конечно). У нас то же самое в методе входа .

В методе выхода из системы мы имеем:

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

Я надеюсь, что это поможет вам.

+2

Это неуклюжий. Просто присвойте 'current' как свойству' UserController' (как уже * уже * в области сеанса!) И установите его на 'null' при выходе из системы (или, лучше,' ExternalContext # invalidateSession() '. См. Также http: //stackoverflow.com/questions/3841361/jsf-http-session-login/3842060#3842060 – BalusC

+0

Я отредактировал сообщение, чтобы заменить мой код на один @BalusC. Я изменил 'FacesContext context = FacesContext.getCurrentInstance (); context.getExternalContext(). GetSessionMap(). Remove ("user"); 'for' FacesContext.getCurrentInstance(). GetExternalContext(). InvalidateSession();' –

Смежные вопросы