Как передать параметры просмотра при переходе от действия в JSF2?

Из действия в моем bean-компоненте я пытаюсь перенаправить на другую страницу, ожидающую параметра представления. Каков рекомендуемый способ сделать это в JSF2?

Например, предположим, что моя исходная страница: http://localhost/page1.xhtml

у него есть commandButton, который вызывает действие:

<h:commandButton value="submit" action="#{myBean.submit}" />

где мой bean выглядит так:

@ManagedBean
@RequestScoped
public class MyBean {

private int id;

public String submit() {
    //Does stuff
    id = setID();
    return "success";
}

А теперь я хочу, чтобы при возврате действия 'submit' переходил к http://localhost/page2.xhtml?id=2

Я пытался сделать это с помощью параметра просмотра в моем случае навигации, но с необычными результатами. Фрагмент faces-config выглядит следующим образом:

<navigation-rule>
    <from-view-id>/page1.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/page2.xhtml</to-view-id>
        <redirect>
            <view-param>
                <name>id</name>
                <value>#{myBean.id}</value>
            </view-param>
        </redirect>
    </navigation-case>
</navigation-rule>

Странное поведение заключается в том, что, хотя myBean настроен на запрос с ограничением области видимости, он вызывает myBean.getId() только при первой загрузке приложения и повторно использует то же значение для всех последующих вызовов, создавая неверные параметры просмотра для страницы 2.

Итак, я ищу либо лучший способ сделать это, либо причину / решение, почему параметр представления не запрашивается у моего bean-компонента каждый раз.


person dule    schedule 31.08.2010    source источник


Ответы (6)


Неинтуитивным в передаче параметров в JSF является то, что вы не решаете, что отправлять (в действии), а скорее то, что хотите получить (на целевой странице).

Когда вы выполняете действие, которое заканчивается перенаправлением, загружаются метаданные целевой страницы, и все необходимые параметры считываются и добавляются к URL-адресу как params.

Обратите внимание, что это точно такой же механизм, как и с любой другой привязкой JSF: вы не можете прочитать значение inputText из одного места и записать его в другом месте. Выражение значения, определенное в viewParam, используется как для чтения (до перенаправления), так и для записи (после перенаправления).

С помощью bean-компонента вы просто делаете:

@ManagedBean
@RequestScoped
public class MyBean {

private int id;

public String submit() {
    //Does stuff
    id = setID();
    return "success?faces-redirect=true&includeViewParams=true";
}

// setter and getter for id

Если на принимающей стороне есть:

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

Он сделает именно то, что вы хотите.

person fdreger    schedule 25.01.2011
comment
Сделал небольшой тест с ним, и я думаю, что он работает так, как я хотел. Спасибо! Хотя предположительно, вы имели в виду успех? Faces-redirect = true & includeViewParams = true; и ‹f: viewParam name = id value = # {myBean.id} /› - person dule; 01.02.2011
comment
Да, прости. Я вставил оба фрагмента кода из рабочего проекта, чтобы избежать опечаток, и вот что: первый взят из шаблона xml (где амперсанд должен быть экранирован) и является неполным, а у другого есть другое имя переменной. Сразу отредактирую. - person fdreger; 02.02.2011
comment
@fdreger, куда бы вы поместили метаданные при использовании h: commandButton? - person Kevin; 06.01.2012
comment
@Kevin: Как и в ответе: метаданные всегда находятся на целевой странице. Не имеет значения, что вы используете на исходной странице (где находится h: commandButton). - person fdreger; 06.01.2012
comment
Что вы делаете, когда целевая страница имеет другой компонент поддержки, чем отправляющая страница? В вашем примере у вас есть имя отправляющего bean-компонента myBean и целевого bean-компонента myBeani. Но на самом деле я не могу сказать, является ли myBeani другим целевым bean-компонентом или i в myBeani - это опечатка. И если у меня есть несколько идентификаторов в моем отправляющем bean-компоненте, например, если у меня есть personId и itemId в моем отправляющем bean-компоненте, в f: viewParam как они реализуются? ‹F: viewParam name = personId value = # {targetBean.personId} /› ‹f: viewParam name = itemId value = # {targetBean.itemId} /› ??? - person Bill Rosmus; 05.11.2012
comment
@BillR: 1) это была опечатка, извините 2) нет отправляющего или получающего bean-компонента - есть viewParam, который привязан к выражению и может получать данные из параметров запроса. Он работает почти так же, как обычный inputText. Если вы хотите создать параметры запроса (изменить значение viewParam), просто добавьте ‹f: param name = '...' value = '...'› в свой commandButton или ссылку. 3) вы можете создать много viewParams, и все они будут работать, так что да, вы можете отправлять и получать несколько параметров. - person fdreger; 05.11.2012
comment
Ответ не совсем правильный. Если вы определяете f:viewParam с тем же именем в исходном представлении и в целевом представлении, то поведение перед навигацией будет таким: попробуйте получить значение параметра через привязку целевого представления; если null, попробуйте через привязку исходного кода. Обнаружено с помощью Mojarra 2.2.5. - person Vsevolod Golovanov; 28.04.2014

Без более приятного решения я обнаружил, что работает просто создание строки запроса в возвращаемом компоненте:

public String submit() {
    // Do something
    return "/page2.xhtml?faces-redirect=true&id=" + id;
}

Не самое гибкое решение, но, похоже, работает так, как я хочу.

Также этот подход используется для очистки процесса построения строки запроса: http://www.warski.org/blog/?p=185

person dule    schedule 02.09.2010
comment
вы все еще используете Faces-config при этом? - person Kevin; 06.01.2012

Обратите внимание на это:

Вам понадобится что-то вроде:

<h:link outcome="success">
  <f:param name="foo" value="bar"/>
</h:link>

...и...

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

Судя по этой странице, что-то вроде этого может быть проще:

 <managed-bean>
   <managed-bean-name>blog</managed-bean-name>
   <managed-bean-class>com.acme.Blog</managed-bean-class>
   <managed-property>
      <property-name>entryId</property-name>
      <value>#{param['id']}</value>
   </managed-property>
 </managed-bean>
person The Alchemist    schedule 31.08.2010
comment
Проблема в том, что я не перехожу сразу на следующую страницу. Мой вопрос относится к навигации из действия bean. Страница 1 вызывает действие bean-компонента, действие bean-компонента делает что-то, возвращает успех, и теперь я хочу перейти к успеху, но добавить параметр представления с перенаправлением. - person dule; 31.08.2010
comment
Извините, я неправильно понял ваш пост. Я думаю, что java.dzone.com/articles/bookmarkability-jsf-2 может получить то, что хочешь. Я думаю, что это именно то, что вы ищете: http://domain/blog/entry.jsf?id=9 - person The Alchemist; 31.08.2010
comment
Спасибо за ответы, но я не уверен, правильно ли понял мой вопрос. Мне непонятно, какой пример вы имеете в виду в этой статье, потому что в ней не обсуждается переход от действия. Самая близкая вещь в статье - передача параметра просмотра на следующую страницу, но я хочу не передавать один и тот же параметр просмотра с одной страницы на другую, скорее я хочу передать новый параметр просмотра на страницу из навигации по действиям. Позвольте мне попытаться перефразировать свой первоначальный вопрос, чтобы понять, смогу ли я прояснить его. - person dule; 01.09.2010
comment
Хм ... вы хотите вставить новый параметр просмотра? Так что-то отличное от whatever.jsf?id=2? Это потребует некоторой интересной работы с JSF. - person The Alchemist; 02.09.2010

Вы можете сделать это с помощью Primefaces следующим образом:

<p:button 
      outcome="/page2.xhtml?faces-redirect=true&amp;id=#{myBean.id}">
</p:button>
person ihebiheb    schedule 04.11.2015

Просто добавьте атрибут visible для тега перенаправления, как показано ниже:

<redirect include-view-params="true">
    <view-param>
        <name>id</name>
        <value>#{myBean.id}</value>
    </view-param>
</redirect>
person Koray Tugay    schedule 17.05.2016

Решение без ссылки на Bean:

<h:button value="login" 
        outcome="content/configuration.xhtml?i=1" />

В моем проекте мне понадобился такой подход:

<h:commandButton value="login" 
        action="content/configuration.xhtml?faces-redirect=true&amp;i=1"  />
person qecce    schedule 16.08.2016
comment
Плохой выбор для использования здесь командной кнопки. Используйте обычную кнопку: stackoverflow.com/questions/13070537/ (то же самое и для PrimeFaces p: button) - person Kukeltje; 16.08.2016