Как метод EL # {bean.id} управляется методом bean bean.getId()

Я действительно не понимаю, как работает геттер и сеттер, это основная концепция. У меня есть следующий код, как атрибут id отправлен в Managed Bean? Захвачен ли он методом геттера?

Мой манекен

<p:inputText id="id" value="#{bean.id}">

Мой управляемый bean

private String id;

public void setId(String id) {
    this.id = id;
}

public String getId() {
      return id;
}

Ответ 1

Вызов методов getter и setter выражениями #{} не является частью JSF, а Язык выражений (наиболее известен как EL). JSF использует EL для привязки данных компонентов HTML к полям bean через правильные геттеры и сеттеры. Это:

  • Если существует bean, Expression Language будет выполнять правильный приемник зарегистрированного bean в правильной области.
  • Если клиент выполняет отправку формы или запрос ajax, то компоненты, которые отправляются на сервер (обычно все компоненты в <h:form>, в случае запросов ajax вы можете указать, какие компоненты отправлять на сервер) будет содержать новое значение, и это значение будет установлено в поле с помощью соответствующего метода настройки.

Например, у вас есть SayHelloBean, который относится к области запроса:

@RequestScoped
@ManagedBean
public class LoginBean {
    private String name;
    //proper getter
    public String getName() {
        return this.name;
    }
    //proper setter
    public void setName(String name) {
        this.name = name;
    }
}

И эти две страницы facelets (так как это пример, я избегаю объявления <html>, <h:head>, <h:body> и других элементов, просто фокусируясь на соответствующем коде)

Page1.xhtml:

<h:form>
    Please tell me your name
    <h:inputText value="#{loginBean.name}" />
    <h:commandButton action="page2" />
</h:form>

Page2.xhtml:

Hello #{loginBean.name}

Вот что происходит за кулисами:

  • Когда загружается файл Page1.xhtml, новый экземпляр LoginBean, который мы можем назвать LoginBean, будет создан JSF и зарегистрирован в области запроса JSP. Поскольку значение <h:inputText /> привязано к LoginBean#name (которое читается как поле name класса LoginBean), тогда EL отобразит значение LoginBean#name (которое читается как поле name экземпляра LoginBean), и поскольку это не инициализировано, EL отобразит null как пустую строку.

  • Когда вы отправляете форму Page1.xhtml, так как LoginBean is @RequestScoped, то JSF создаст новый экземпляр LoginBean, который мы можем назвать его loginBean2 (добавление 2 в конец, потому что этот экземпляр полностью отличается от ранее созданного LoginBean) и зарегистрирует его в области запросов JSP. Поскольку значение <h:inputText /> привязано к LoginBean#name, JSF будет проверять и устанавливать данные, вызывая правильный сеттер. Это сделает loginBean2#name значение <input type="text">, которое было показано <h:inputText/>.

  • Наконец, JSF обязательно перейдет к Page2.xhtml через forward, где при его обработке он найдет #{loginBean.name}, а EL проверит значение loginBean2#name и заменит его.

Шаги, объясненные здесь, являются очень небольшим объяснением (и с множеством элементов, которые не объясняются) жизненного цикла JSF, и как JSF использует геттеры и сеттеры.

Дополнительная информация:


Дополнительное примечание: поскольку вы изучаете JSF, избегайте ввода кода бизнес-логики в getters/seters. Это объясняется здесь: Почему JSF вызывает геттеры несколько раз

Ответ 2

Всякий раз, когда вы используете что-то вроде

#{someBean.someField}

EL ищет метод someBean.getSomeField() или someBean.setSomeField(...), в зависимости от того, читаете ли вы это поле или записываете в него (что легко можно вывести из контекста). JSF никогда не обращается к полю напрямую (т.е. Без использования его геттера или сеттера). Попробуйте удалить получателя и сеттер заданного поля, и вы увидите, что это не сработает.