Привязка компонента vs findComponent() - когда использовать какой?

Как описано в этом вопросе, я пытаюсь выполнить некоторую проверку поля в форме на стороне bean. Для этого я хотел бы получить доступ к посторонним полям, чтобы отметить их. Из поиска в Интернете есть два способа сделать это:

  • сохраните компоненты в резервной копии bean для доступа и используйте их на страницах JSF с помощью атрибута binding.
  • Используйте привязку стандартного значения на страницах JSF и при необходимости доступа к компоненту из bean, просмотрите его с помощью UIViewRoot.findComponent(String id)

Насколько я вижу, оба способа имеют недостатки: Компонентные привязки взрывают подложку bean с помощью переменных и геттеров/сеттеров, некоторые сайты сильно препятствуют использованию связывания компонентов вообще. В любом случае, запрашивается область запроса. С другой стороны, findComponent() всегда пересекает дерево, которое может быть или не быть дорогостоящим, не так ли? (Кроме того, на данный момент я не могу найти свой компонент вообще, но это еще одна проблема)

Каким будет путь? Являются ли эти взаимозаменяемые альтернативы, а если нет, то на основании каких критериев вы выбрали? В настоящее время я просто недостаточно понимаю, чтобы принять достойное решение...

Ответ 1

Прежде всего, независимо от выбора, обе они являются плохой практикой. См. Также Как работает атрибут привязки в JSF? Когда и как его использовать?

Если вам нужно было сделать выбор, привязки компонентов определенно быстрее и дешевле. Это логично понимает, что сканирование дерева, выполняемое UIComponent#findComponent(), имеет свои последствия для производительности.

В самом деле, поддержка bean, содержащая привязки компонентов, должна быть областью с запросом, но вы можете легко добавить другую область подкачки bean, содержащую в ней бизнес-логику @ManagedProperty.

Более чистым подходом было бы использовать Map как держатель всех привязок компонентов. Вам нужно добавить следующую запись в faces-config.xml:

<managed-bean>
    <managed-bean-name>components</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Это можно просто использовать как

<h:inputSome binding="#{components.input1}" />
<h:inputSome binding="#{components.input2}" />
<h:inputSome binding="#{components.input3}" />

И это можно получить в другом beans как

Map<String, UIComponent> components = (Map<String, UIComponent>) externalContext.getRequestMap().get("components");

Таким образом, вам не нужно беспокоиться о том, чтобы указать отдельные свойства/геттеры/сеттеры. В приведенном выше примере Map будет содержать три записи с ключами input1, input2 и input3, каждый из которых имеет соответствующий экземпляр UIComponent как значение.


Несвязанный к конкретному вопросу, может быть гораздо более простое решение конкретной проблемы, как вы описали в другом вопросе, чем выполнение проверки в методе действий (что фактически является плохим дизайном). Там я отправил ответ.