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

149

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

<f:metadata>
    <f:viewParam id="id" value="#{bean.id}" />
    <f:viewAction action="#{bean.init}" />
</f:metadata>
Hanynowsky
источник

Ответы:

288

Параметры 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устанавливается в компоненте таким образом, прямо перед отображением представления.

Что касается валидации, то в следующем примере устанавливается параметр 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имеет также<f:viewParam> на то же параметр, в противном случае он не будет пропущен.


Используйте GET формы в JSF

<f:viewParam>Также может быть использован в сочетании с «простой HTML» GET формы.

<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бобом:

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 (она делает это уже «под прикрытием»).


Смотрите также:

BalusC
источник
@BalusC Какой должна быть область действия «bean» при использовании вместе с Face-Redirect = True? Будет ли это работать так, как ожидается, если для области задано значение «@RequestScoped»?
Компьютерщик
@Geek: редирект создает новый запрос GET. Область действия bean-компонента исходного и целевого компонентов не имеет значения. Однако вы должны принять во внимание возможные последствия нового запроса GET для запроса и просмотреть объект bean-объекта. Смотрите также stackoverflow.com/questions/7031885/...
BalusC
@BalusC Что именно вы подразумеваете под «Однако вы должны принять во внимание возможные последствия нового запроса GET для запроса и просмотреть объект bean-объекта».
Компьютерщик
@ Geek: Они будут уничтожены и воссозданы, потому что их область действия тогда закончится и начнется.
BalusC
@BalusC. Комплексный ответ. «Когда вам нужно использовать функцию типа« @ »PostConstruct для просмотра объединенных компонентов, которая не вызывается при каждом запросе, проверьте, не является ли запрос обратной передачей». Если он не вызывается при каждом запросе, тогда зачем проверять, является ли запрос обратной передачей или нет?
Улук Бий,