Для чего можно использовать <f: metadata>, <f: viewParam> и <f: viewAction>?

Может ли кто-нибудь уточнить, как мы можем использовать в целом или в реальном мире пример этого фрагмента?

<f:metadata>
    <f:viewParam id="id" value="#{bean.id}" />
    <f:viewAction action="#{bean.init}" />
</f:metadata>

Ответ 1

Параметры процесса GET

<f:viewParam> управляет настройкой, преобразованием и проверкой параметров GET. Это похоже на <h:inputText>, но затем для параметров GET.

Следующий пример

<f:metadata>
    <f:viewParam name="id" value="#{bean.id}" />
</f:metadata>

выполняет в основном следующее:

  • Получить значение параметра запроса по имени id.
  • При необходимости преобразуйте и подтвердите его (вы можете использовать атрибуты required, validator и converter и вложить в него <f:converter> и <f:validator> в нем, как и в случае с <h:inputText>)
  • Если преобразование и проверка успешно завершены, установите его как свойство bean, представленное значением #{bean.id}, или если атрибут value отсутствует, тогда установите его как атрибут запроса на имя id, чтобы он был доступен на #{id} в представлении.

Поэтому, когда вы открываете страницу как foo.xhtml?id=10, тогда значение параметра 10 устанавливается в bean таким образом, прямо перед визуализацией представления.

Что касается проверки, следующий пример устанавливает параметр в required="true" и допускает только значения от 10 до 20. Любой отказ проверки приведет к отображению сообщения.

<f:metadata>
    <f:viewParam id="id" name="id" value="#{bean.id}" required="true">
        <f:validateLongRange minimum="10" maximum="20" />
    </f:viewParam>
</f:metadata>
<h:message for="id" />

Выполнение бизнес-действий по параметрам GET

Вы можете использовать <f:viewAction> для этого.

<f:metadata>
    <f:viewParam id="id" name="id" value="#{bean.id}" required="true">
        <f:validateLongRange minimum="10" maximum="20" />
    </f:viewParam>
    <f:viewAction action="#{bean.onload}" />
</f:metadata>
<h:message for="id" />

с

public void onload() {
    // ...
}

Однако <f:viewAction> является новым, поскольку JSF 2.2 (<f:viewParam> уже существует с JSF 2.0). Если вы не можете обновить, то лучше всего использовать <f:event>.

<f:event type="preRenderView" listener="#{bean.onload}" />

Это, однако, используется для каждого запроса. Вам нужно явно проверить, не является ли запрос обратной почтой:

public void onload() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // ...
    }
}

Если вы также хотите пропустить также случаи с ошибкой "Конверсия/проверка", выполните следующие действия:

public void onload() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (!facesContext.isPostback() && !facesContext.isValidationFailed()) {
        // ...
    }
}

Используя <f:event>, этот способ, по сути, является обходным/взломанным, именно поэтому <f:viewAction> был введен в JSF 2.2.


Параметры просмотра в следующем представлении

Вы можете "пропустить" параметры представления в ссылках навигации, установив атрибут includeViewParams в true или добавив параметр запроса includeViewParams=true.

<h:link outcome="next" includeViewParams="true">
<!-- Or -->
<h:link outcome="next?includeViewParams=true">

который генерирует с приведенным выше примером <f:metadata> в основном следующую ссылку

<a href="next.xhtml?id=10">

с исходным значением параметра.

Этот подход требует только, чтобы next.xhtml имел также a <f:viewParam> в том же параметре, иначе он не будет передан.


Использовать формы GET в JSF

<f:viewParam> также может использоваться в сочетании с формами GET "plain HTML".

<f:metadata>
    <f:viewParam id="query" name="query" value="#{bean.query}" />
    <f:viewAction action="#{bean.search}" />
</f:metadata>
...
<form>
    <label for="query">Query</label>
    <input type="text" name="query" value="#{empty bean.query ? param.query : bean.query}" />
    <input type="submit" value="Search" />
    <h:message for="query" />
</form>
...
<h:dataTable value="#{bean.results}" var="result" rendered="#{not empty bean.results}">
     ...
</h:dataTable>

В основном это @RequestScoped bean:

private String query;
private List<Result> results;

public void search() {
    results = service.search(query);
}

Обратите внимание, что <h:message> предназначен для <f:viewParam>, а не для простого HTML <input type="text">! Также обратите внимание, что входное значение отображает #{param.query}, когда #{bean.query} пуст, потому что переданное значение в противном случае вообще не отображалось при наличии ошибки проверки или преобразования. Обратите внимание, что эта конструкция недействительна для входных компонентов JSF (она уже делает это под обложками).


См. также: