Як це працює?
Коли перегляд JSF (файл Facelets / JSP) буде побудований / відновлений, буде створено дерево компонентів JSF. На той момент, час побудови подання , binding
обчислюються всі атрибути ( разом з id
атрибутами та тахелендерами, як JSTL ). Коли компонент JSF потрібно створити перед додаванням до дерева компонентів, JSF перевірить, чи binding
повертає атрибут попередньо створений компонент (тобто не- null
), а якщо так, то використовуйте його. Якщо його не створити попередньо, тоді JSF автоматично створить компонент "звичайним способом" і викличе установку за binding
атрибутом із автоматично створеним екземпляром компонента як аргументом.
В результаті він пов'язує посилання на екземпляр компонента в дереві компонентів із змінною області дії. Ця інформація жодним чином не видно у згенерованому HTML-представленні самого компонента. Ця інформація в жодному разі не має відношення до згенерованого виводу HTML. Коли форма подається і подання відновлюється, дерево компонентів JSF просто відновлюється з нуля, і всі binding
атрибути будуть просто переоцінені, як описано вище у параграфі. Після відтворення дерева компонентів JSF відновить стан перегляду JSF у дереві компонентів.
Екземпляри компонентів мають масштаб запиту!
Важливо знати і розуміти, що конкретні екземпляри компонентів ефективно вимагають масштабування. Вони створюються щоразу за кожним запитом, а їх властивості заповнюються значеннями стану JSF на етапі перегляду відновлення. Отже, якщо ви прив'язуєте компонент до властивості резервного компонента, тоді резервний компонент абсолютно не повинен знаходитись у ширшому обсязі, ніж область запиту. Див. Також специфікацію JSF 2.0, розділ 3.1.5:
3.1.5 Прив’язка компонентів
...
Прив'язки компонентів часто використовуються разом із JavaBeans, які динамічно створюються за допомогою засобу створення керованого компонента (див. Розділ 5.8.1 "VariableResolver і VariableResolver за замовчуванням"). Наполегливо рекомендується розробникам додатків розміщувати керовані компоненти, на які вказують вирази прив'язки компонентів, у область "запит". Це пов’язано з тим, що розміщення його в сесії або області застосування вимагатиме захисту потоків, оскільки екземпляри UIComponent залежать від запуску всередині одного потоку. Також є потенційно негативні наслідки для управління пам’яттю при розміщенні прив’язки компонентів до “сеансу”.
В іншому випадку екземпляри компонентів розподіляються між кількома запитами, що може призвести до помилок " дублювання ідентифікатора компонента " та "дивної" поведінки, оскільки валідатори, перетворювачі та слухачі, оголошені у поданні, знову приєднуються до існуючого екземпляра компонента з попереднього запиту (запитів). Симптоми зрозумілі: вони виконуються кілька разів, ще один раз із кожним запитом в тому ж обсязі, до якого компонент прив'язаний.
І під великим навантаженням (тобто, коли кілька різних HTTP-запитів (потоків) одночасно отримують доступ до того самого екземпляра компонента та маніпулюють ним), ви можете рано чи пізно зіткнутися з аварійним завершенням роботи програми, наприклад із застрягшим потоком на UIComponent.popComponentFromEL або Java Threads при 100% використанні центрального процесора з використанням багатофункціональних інтерфейсів UIDataAdaptorBase та його внутрішньої HashMap , або навіть якогось "дивного" IndexOutOfBoundsException
або ConcurrentModificationException
виходить прямо з вихідного коду реалізації JSF, поки JSF зайнятий збереженням або відновленням стану перегляду (тобто трасування стека вказує saveState()
або restoreState()
методи тощо).
Використання binding
властивості квасолі - погана практика
Незважаючи на те, що використання binding
цього способу прив'язка цілого екземпляра компонента до властивості bean, навіть за запитом з обсягом bean, є у JSF 2.xa досить рідкісним випадком використання і, як правило, не найкращою практикою. Це вказує на дизайнерський запах. Ви нормально оголошуєте компоненти осторонь зору і зв'язати їх виконання атрибутів , як value
і , можливо , інші , як styleClass
, disabled
, rendered
і т.д., для нормальних властивостей компонента. Потім ви просто маніпулюєте саме тим властивістю bean, яке хочете, замість того, щоб захопити весь компонент і викликати метод setter, пов'язаний з атрибутом.
У тих випадках , коли компонент повинен бути «динамічно побудована» на основі статичної моделі, краще використовувати час перегляду збірки теги , як JSTL , якщо це необхідно в файлі тегів , замість того createComponent()
, new SomeComponent()
, getChildren().add()
а що ні. Див. Також Як рефакторувати фрагмент старого JSP до якогось еквівалента JSF?
Або, якщо компонент повинен бути «динамічно виявляється» на основі динамічної моделі, а потім просто використовувати компонент ітератора ( <ui:repeat>
, <h:dataTable>
і т.д.). Див. Також Як динамічно додавати компоненти JSF .
Композитні компоненти - це зовсім інша історія. Повністю законно прив'язувати компоненти всередині a <cc:implementation>
до резервного компонента (тобто компонента, ідентифікованого <cc:interface componentType>
. Див. Також ao Розділити java.util.Date протягом двох годин: поля inputText, що представляють годину та хвилину за допомогою f: convertDateTime та Як реалізувати динамічний список за допомогою композитний компонент JSF 2.0?
Використовувати лише binding
у місцевому масштабі
Однак іноді вам хочеться дізнатись про стан іншого компонента зсередини певного компонента, частіше у випадках використання, пов’язаних із валідацією, залежною від дії / значення. Для цього binding
можна використовувати атрибут, але не в поєднанні з властивістю bean. Ви можете просто вказати унікальне ім'я змінної в локальній області EL в binding
атрибуті так, binding="#{foo}"
і компонент знаходиться під час відповіді на візуалізацію в іншому місці в тому ж поданні, як UIComponent
посилання, доступне #{foo}
. Ось кілька супутніх питань, де у відповіді було використано таке рішення:
Дивитися також:
User.User(), User.getLink(), User.setLink(), User.getValue()
Коли я натискаю посилання =User.User(), User.setLink()...