Вопрос по jsf-2, flash-scope, jsf – Понимать область применения Flash в JSF2

29

Насколько я понимаю, объекты, помещенные в область действия Flash в жизненном цикле запроса граней, будут доступны для следующего жизненного цикла запроса граней, а затем очищены.

Предположим, у меня есть две страницы:

page01.xhtml:

<h:form>
    <h:commandButton  action="#{page01Bean.action}" />
</h:form>

Page01Bean :

@ManagedBean
@RequestScoped
public class Page01Bean {

        public void action(){
            FacesContext.getCurrentInstance().getExternalContext().getFlash().put("fooKey", "fooValue");
        }

}

page02.xhtml:

<h:outputText value="#{flash.fooKey}"/> 

Поэтому, когда кнопка вpage01.xhtml щелкает, запускается жизненный цикл запроса граней (скажем, жизненный цикл A) и устанавливается значение в flash под клавишей под названиемfooKey

Затем я открываю другую вкладку браузера и просматриваюpage02.xhtml , Другой жизненный цикл запроса лиц (скажем, жизненный цикл B) начинает отображать эту страницу. Я ожидал, что жизненный цикл B может получить доступ к области флэш-памяти предыдущего жизненного цикла (то есть жизненному циклу A) и отобразитьfooValueвpage02.xhtml, Однако ничего не отображается.

Пожалуйста, исправьте меня в том, что я неправильно понимаю в области действия вспышки в этом примере. Спасибо

Ваш Ответ

2   ответа
24

но для полноты картины я хотел бы сказать, чтомного вопросов в реализациях Mojarra со всем этим, но в итоге они достигли правильной работы в версиях Mojarra 2.1.27 и 2.2.5.

Как говорит @Gamb, цель области действия флэш-памяти состоит в том, чтобы поддерживать параметр в активном состоянии, отображая его внутри перенаправления. Мы также можем сохранить параметр дольше, если нам это нужно. Помимо упомянутого способа,FacesContext#getCurrentInstance#getExternalContext#getFlash#putтакже имеется возможность установить параметр с помощью выражения EL, используя<c:set />, Я выполнил базовый тест послеSSCCE который показывает более широкий диапазон параметров, используя два представления:

Bean1

@ManagedBean
@ViewScoped
public class Bean1 implements Serializable {

    /**
     * Just takes the given param, sets it into flash context and redirects to
     * page2
     * 
     * @param inputValue
     * @return
     */
    public String goPage2(String inputValue) {
        FacesContext.getCurrentInstance().getExternalContext().getFlash()
                .put("param", inputValue);
        return "page2?faces-redirect=true";
    }

}

page1.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head />
<h:body>

    <!-- Sets the first flash param at the action method, which redirects to page 2 -->
    <h:form>
        <h:inputText value="#{inputValue}" />
        <h:commandButton action="#{bean1.goPage2(inputValue)}"
            value="Go Page 2" />
    </h:form>

    <!-- Sets the second flash param -->
    <c:set target="#{flash}" property="param2" value="Myparam2" />

    <!-- Tries to retrieve both of the params. 
    Note none of them is displayed at the first page hit.
    If page refreshed, the second param which has been already set 
    using c:set above, will be displayed -->
    <p>Param1: #{flash['param']}</p>
    <p>Param2: #{flash['param2']}</p>
</h:body>
</html>

Bean2

@ManagedBean
@ViewScoped
public class Bean2 implements Serializable {

    public String getParam() {
        /**
         * Takes the parameter from the flash context
         */
        return (String) FacesContext.getCurrentInstance().getExternalContext()
                .getFlash().get("param");
    }

}

page2.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core">
<h:head />
<!-- This page just displays the received params -->
<h:body>
    <!-- Different ways to retrieve the params from the flash scope -->
    <p>Param1: #{bean2.param}</p>
    <p>Param1: #{flash.param}</p>
    <p>Param1: #{flash['param']}</p>
    <p>Param2: #{flash['param2']}</p>

    <!-- Keep the first param for next redirection -->
    #{flash.keep.param}

    <!-- Return to page1 and see how the first param is retained -->
    <h:button outcome="page1?faces-redirect=true" value="return to 1" />
</h:body>
</html>

See also:

JSF flash documentation Keeping the flash parameters when user manually reloads the view
+1 за упоминание глючной реализации, это чертовски смутило меня.
Установить его на EL не помогло, но вместо этого я могу предложить поместить его в управляемый компонент:FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("oValue"); this.oValue = (ValueClass) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("oValue");  Это работает дляGETснова, но она как-то ломается после ajax-запроса +GET.
32

переменные, хранящиеся в области видимости флэш-памяти, сохранят перенаправление и впоследствии будут отброшены. Это действительно полезно при реализации шаблона Post-Redirect-Get.

Если вы попытаетесь перейти на другую страницу путем перенаправления и доступа к атрибутам при загрузке, они будут там. После выполнения этого запроса значения во флэш-памяти будут отброшены. Например:

Вы находитесь на странице page1.xhtml, и у вас есть commandLink, который перенаправляет на новую страницу с помощью метода, подобного этому (Примечание: я буду использовать неявную навигацию).

public String navigateToPageB() {
    FacesContext.getCurrentInstance().getExternalContext().getFlash().put("param1", "Hello World!");
    return "pageB?faces-redirect=true";
}

Когда рендерит pageB.xhtml, вы можете получить доступ к этим значениям с помощью выражений EL, таких как

<h:outputLabel value="#{flash['param1']}" />

который будет отображать & quot; Hello World! & quot; Строка, которую мы сохранили ранее в navigateToPageB.

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

Похожие вопросы