Ответ 1
Как это работает?
При создании/восстановлении представления JSF (Facelets/JSP file) будет создано дерево компонентов JSF. В этот момент время сборки просмотров оцениваются все атрибуты binding
(вместе с id
атрибутами и обработчиками меток, такими как JSTL). Когда компонент JSF должен быть создан до его добавления в дерево компонентов, JSF проверяет, возвращает ли атрибут binding
предварительно обработанный компонент (т.е. Не null
), и если да, то используйте его. Если он не будет создан, то JSF автоматически создаст компонент "обычный способ" и вызовет сеттер за атрибутом binding
с экземпляром autocreated component в качестве аргумента.
В эффектах он связывает ссылку экземпляра компонента в дереве компонентов с областью переменной. Эта информация никоим образом не отображается в сгенерированном представлении HTML самого компонента. Эта информация никоим образом не связана с генерируемым выходом HTML. Когда форма отправляется и представление восстанавливается, дерево компонентов JSF просто перестраивается с нуля, и все атрибуты binding
просто переоцениваются, как описано в предыдущем абзаце. После воссоздания дерева компонентов JSF восстановит состояние представления JSF в дереве компонентов.
Экземпляры компонентов - это область с запросом!
Важно знать и понимать, что конкретные экземпляры компонентов эффективно запрашивают область действия. Они создаются по каждому запросу, и их свойства заполняются значениями из состояния просмотра JSF во время фазы просмотра. Итак, если вы привязываете компонент к свойству поддержки bean, то поддержка bean должна абсолютно не находиться в более широкой области, чем область запроса. См. Также Спецификация JSF 2.0 глава 3.1.5:
3.1.5 Компонентные привязки
...
Связывание компонентов часто используется в сочетании с JavaBeans, которые динамически создаются с помощью управляемых bean Объект создания (см. раздел 5.8.1 "VariableResolver и Default VariableResolver" ). Это сильно рекомендуется, чтобы разработчики приложений размещали управляемые beans, на которые указывали выражения привязки компонентов в "запрос". Это связано с тем, что размещение его в сеансе или области приложения потребует безопасности потоков, поскольку Экземпляры UIComponent зависят от запуска внутри одного потока. Возможны также негативные последствия для управления памятью при размещении привязки компонента в области "сеанс".
В противном случае экземпляры компонентов распределяются между несколькими запросами, что может привести к ошибкам "дублировать идентификатор компонента и" странным" поведением, поскольку валидаторы, преобразователи и слушатели, объявленные в вид повторно присоединяются к существующему экземпляру компонента из предыдущего запроса (-ов). Симптомы ясны: они выполняются несколько раз, один раз с каждым запросом в той же области, в которой был связан компонент.
И при большой нагрузке (т.е. когда несколько разных HTTP-запросов (потоков) одновременно обрабатывают и обрабатывают один и тот же экземпляр компонента), вы можете столкнуться рано или поздно с крахом приложения, например. Застрял поток в UIComponent.popComponentFromEL или Java Threads при 100% использовании ЦП с использованием богатых интерфейсов UIDataAdaptorBase и его внутренней HashMap, или даже некоторые "странные" IndexOutOfBoundsException
или ConcurrentModificationException
, идущие прямо из исходного кода реализации JSF, в то время как JSF занят сохранением или восстановлением состояния представления (т.е. трассировка стека показывает методы saveState()
или restoreState()
и т.п.).
Использование binding
в bean - это плохая практика
Независимо от этого, используя binding
таким образом, привязка всего экземпляра компонента к свойству bean, даже в области с привязкой к запросу bean, находится в JSF 2.x довольно редкий случай использования и, как правило, не самая лучшая практика. Это указывает на запах дизайна. Обычно вы объявляете компоненты на стороне представления и связываете их атрибуты времени выполнения, такие как value
и, возможно, другие, такие как styleClass
, disabled
, rendered
и т.д., С обычными свойствами bean. Затем вы просто управляете именно этим свойством bean, а не захватываете весь компонент и вызываете метод setter, связанный с этим атрибутом.
В случаях, когда компонент должен быть "динамически построен" на основе статической модели, лучше использовать просмотр тегов времени построения, таких как JSTL, при необходимости в файл тега, вместо createComponent()
, new SomeComponent()
, getChildren().add()
, а что нет. См. Также Как отредактировать фрагмент старого JSP на эквивалент JSF?
Или, если компонент должен быть "динамически визуализирован" на основе динамической модели, просто используйте компонент итератора (<ui:repeat>
, <h:dataTable>
, и т.д). См. Также Как динамически добавлять компоненты JSF.
Составные компоненты - совершенно другая история. Полностью законно связывать компоненты внутри <cc:implementation>
с компонентом поддержки (т.е. Компонентом, идентифицированным <cc:interface componentType>
. См. Также ao Разделить java.util.Date на два h: поля inputText представляя час и минуту с помощью f: convertDateTime и Как реализовать динамический список с составным компонентом JSF 2.0?
Используйте только binding
в локальной области
Однако иногда вы хотите узнать о состоянии другого компонента изнутри определенного компонента, чаще, чем часто в случаях использования, связанных с проверкой на действие/значение. Для этого можно использовать атрибут binding
, но не в сочетании с свойством bean. Вы можете указать только имя локальной переменной локального EL-области в атрибуте binding
, например, binding="#{foo}"
, и этот компонент находится во время отклика в другом месте в том же представлении, что и ссылка UIComponent
, доступная #{foo}
. Вот несколько связанных вопросов, в которых такое решение используется в ответе:
- Подтвердите ввод, если требуется, только если нажата некоторая кнопка управления
- Как визуализировать компонент только в том случае, если другой компонент не отображается?
- JSF 2 dataTable индекс строки без dataModel
- По умолчанию зависит selectOneMenu и требуется = "true"
- Проверять группу полей по мере необходимости, когда по крайней мере один из них заполнен
- Как изменить класс css для ввода и метки при завершении проверки?
- Получение JSF-компонента с Javascript
-
Используйте выражение EL для передачи идентификатора компонента в составной компонент в JSF
(и это только с последнего месяца...)