Почему JSF сохраняет состояние компонентов пользовательского интерфейса на сервере?

108
  1. До какого момента времени JSF сохраняет состояние компонентов пользовательского интерфейса на стороне сервера и когда именно информация о состоянии компонента пользовательского интерфейса удаляется из памяти сервера? Когда вошедший в систему пользователь приложения будет перемещаться по страницам, будет ли состояние компонентов накапливаться на сервере?

  2. Я не понимаю, в чем преимущество сохранения состояния компонентов пользовательского интерфейса на сервере !? Разве недостаточно прямой передачи проверенных / преобразованных данных в управляемые компоненты? Могу я или должен попытаться избежать этого?

  3. Разве это не потребляет слишком много памяти на стороне сервера, если есть тысячи одновременных пользовательских сеансов? У меня есть приложение, в котором пользователи могут публиковать блоги по определенным темам. Эти блоги довольно большие по размеру. Когда будут отправлены ответные сообщения или запрос на просмотр блогов, будут ли сохранены эти большие данные страницы как часть состояния компонентов? Это съело бы слишком много памяти. Разве это не беспокоит?


Обновление 1:

Теперь нет необходимости сохранять состояние при использовании JSF. Доступна высокопроизводительная реализация JSF без сохранения состояния. См. Этот блог и этот вопрос для получения более подробной информации и обсуждения. Кроме того, есть открытая проблема, которую следует включить в спецификации JSF, возможность предоставить режим без сохранения состояния для JSF. (PS Рассмотрите возможность голосования по вопросам this и this, если это полезная функция для вас.)


Обновление 2 (24-02-2013):

Отличная новость, что Mojarra 2.1.19 вышла с режимом без сохранения состояния !

Посмотреть здесь:

http://weblogs.java.net/blog/mriem/archive/2013/02/08/jsf-going-stateless?force=255

http://java.net/jira/browse/JAVASERVERFACES-2731

http://balusc.blogspot.de/2013/02/stateless-jsf.html

Раджат Гупта
источник

Ответы:

199

Почему JSF нужно сохранять состояние компонентов пользовательского интерфейса на стороне сервера?

Поскольку HTTP не имеет состояния, а JSF - это состояние. Дерево компонентов JSF подвержено динамическим (программным) изменениям. JSF просто необходимо знать точное состояние, которое было, когда форма была отображена для конечного пользователя, чтобы он мог успешно обработать весь жизненный цикл JSF на основе информации, предоставленной исходным деревом компонентов JSF, когда форма была отправлена ​​обратно в сервер. Дерево компонентов предоставляет информацию об именах параметров запроса, необходимых преобразователях / валидаторах, свойствах связанных управляемых компонентов и методах действий.


До какого момента времени JSF сохраняет состояние компонентов пользовательского интерфейса на стороне сервера и когда именно информация о состоянии компонента пользовательского интерфейса удаляется из памяти сервера?

Эти два вопроса, кажется, сводятся к одному и тому же. В любом случае, это зависит от реализации и также зависит от того, сохраняется ли состояние на сервере или на клиенте. Немного приличная реализация удалит его, когда срок его действия истек или когда очередь заполнена. Например, Mojarra имеет ограничение по умолчанию в 15 логических представлений, когда для сохранения состояния установлено значение сеанс. Это можно настроить с помощью следующего параметра контекста в web.xml:

<context-param>
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>15</param-value>
</context-param>

См. Также FAQ Mojarra для других параметров, специфичных для Mojarra, и соответствующий ответ com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews


Когда вошедший в систему пользователь приложения будет перемещаться по страницам, будет ли состояние компонентов накапливаться на сервере?

Технически это зависит от реализации. Если вы говорите о межстраничной навигации (просто запросы GET), то Мохарра ничего не сохраняет в сеансе. Однако, если они являются запросами POST (формы с командными ссылками / кнопками), то Mojarra сохранит состояние каждой формы в сеансе до максимального предела. Это позволяет конечному пользователю открывать несколько форм на разных вкладках браузера в одном сеансе.

Или, если для сохранения состояния установлено значение client, JSF не будет ничего сохранять в сеансе. Вы можете сделать это с помощью следующего параметра контекста в web.xml:

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

Затем он будет сериализован в зашифрованную строку в скрытом поле ввода с именем javax.faces.ViewStateформы.


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

Этого недостаточно для обеспечения целостности и надежности JSF. JSF - это динамическая структура с единой точкой входа для управления. Без государственного управления, один смогут пародия / хак HTTP запросы определенным образом (например , манипулирование disabled, readonlyи renderedатрибуты), чтобы JSF делать разные й потенциально hazardful- вещи. Он даже будет подвержен атакам CSRF и фишингу.


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

Память стоит особенно дешево. Просто дайте серверу приложений достаточно памяти. Или, если пропускная способность сети для вас дешевле, просто переключите сохранение состояния на клиентскую сторону. Чтобы найти наилучшее соответствие, просто проведите стресс-тест и профилируйте свое веб-приложение с ожидаемым максимальным количеством одновременных пользователей, а затем предоставьте серверу приложений 125% ~ 150% максимальной измеренной памяти.

Обратите внимание, что JSF 2.0 значительно улучшил управление состоянием. Можно сохранить частичное состояние (например, будет сохранено только то <h:form>, а не все от <html>всего до конца). Например, это делает Мохарра. Средняя форма с 10 полями ввода (каждое с меткой и сообщением) и 2 кнопками займет не более 1 КБ. При 15 просмотрах в сеансе это должно быть не более 15 КБ за сеанс. При ~ 1000 одновременных пользовательских сессиях это должно быть не более 15 МБ.

Ваше внимание должно быть больше сосредоточено на реальных объектах (управляемых bean-компонентах и ​​/ или даже объектах БД) в области сеанса или приложения. Я видел много кодов и проектов, которые без надобности дублируют всю таблицу базы данных в память Java в виде bean-компонента с ограниченным сеансом, где Java используется вместо SQL для фильтрации / группировки / упорядочивания записей. При ~ 1000 записей это легко превысит 10 МБ на сеанс пользователя .

BalusC
источник
1
Вы можете прояснить № 2? Почему нельзя просто воссоздавать дерево компонентов для каждого запроса? Какое состояние действительно нужно сохранять между запросами и почему? Похоже, что единственная причина для сохранения дерева компонентов между запросами - это производительность.
Райан,
Более конкретный вопрос здесь: stackoverflow.com/questions/7349174/…
Райан,
Ваш ответ был мне очень понятен! Проблемы производительности и масштабируемости JSF имеют непосредственное отношение к реализации программиста! Необходимо знать, как правильно использовать технологию!
Лукас Батистусси
«Просто дайте серверу приложений достаточно памяти». У меня сложилось впечатление, что мы говорим здесь о вещах корпоративного уровня, если мы говорим о тысячах одновременных пользовательских сеансов. Если у вас есть оборудование корпоративного уровня на предприятии, вы не можете просто «предоставить серверу приложений достаточно памяти», как вы можете сделать это дома с Linux.
stu
Ваш ответ был очень ясным, и спасибо за это. Почему исчезает область действия JSF flash, если для javax.faces.PARTIAL_STATE_SAVING установлено значение true. getFacesContext (). getExternalContext (). getFlash (). put ("buildingId", buildingId).
May Thet