Понимать область применения Flash в JSF2
Насколько я понимаю, объекты, помещенные в область действия 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 ответа
Короче говоря, переменные, хранящиеся в области видимости флэш-памяти, сохранят перенаправление и впоследствии будут отброшены. Это действительно полезно при реализации шаблона 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']}" />
который будет отображать "Hello World!" Строка, которую мы сохранили ранее в navigateToPageB.
Что касается вашего вопроса, открывая новую вкладку в вашем проводнике, вы не получаете доступ к тому же контексту, который вы использовали на предыдущей вкладке, поэтому ваша переменная там будет недоступна.
Предыдущий ответ верен, но просто для полноты я хотел бы сказать, что в реализациях 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>
Смотрите также: