了解JSF2中的Flash范围

据我所知,放置在一个faces请求生命周期的Flash范围内的对象将可用于下一个faces请求生命周期,然后清除。

假设我有两个页面:

page01.xhtml

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

Page01豆:

 @ManagedBean @RequestScoped public class Page01Bean { public void action(){ FacesContext.getCurrentInstance().getExternalContext().getFlash().put("fooKey", "fooValue"); } } 

page02.xhtml

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

所以当点击page01.xhtml中的button时,一个faces请求生命周期(比如生命周期A)就会启动,并将这个值设置为fooKey这个键下的fooKey

然后我打开另一个浏览器选项卡并浏览page02.xhtml 。 另一个面临请求生命周期(比如生命周期B)开始渲染这个页面。 我期望生命周期B可以访问其以前的生命周期的范围(即生命周期A),并在page02.xhtml显示page02.xhtml 。 但是,它什么也没有显示。

请纠正我对这个例子中闪存范围的误解。 非常感谢

简而言之,存储在闪存范围中的variables将在redirect后存活,并在之后被丢弃。 这在实现Post-Redirect-Get模式时非常有用。

如果您尝试通过redirect导航到另一个页面并访问加载时的属性,它们将在那里。 在请求完成后,闪存中的值将被丢弃。 例如:

你在page1.xhtml中,你有一个commandLink,用这样的方法redirect到一个新的页面(注意:我将使用隐式导航)。

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

当pageB.xhtml被渲染时,你可以通过ELexpression式来访问这些值,比如

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

这将显示“Hello World!” 我们之前保存在navigateToPageB中的string。

至于你的问题,通过在你的资源pipe理器中打开一个新的标签,你不能访问你在前一个标签上访问的同一个环境,所以你的variables将不可用。

以前的答案是正确的,但是为了完整性,我想说的是,在所有这些东西中都有很多 Mojarra实现中的问题 ,但最终他们实现了在Mojarra 2.1.27和2.2.5版本中正常工作。

正如@Gamb所说,Flash范围的目标是保持一个参数在redirect内部的映射。 如果我们需要的话,我们也可以保持这个参数更长的时间。 除了上面提到的方法, FacesContext#getCurrentInstance#getExternalContext#getFlash#put ,还有机会通过ELexpression式使用<c:set />设置参数。 我已经在SSCCE之后实施了一个基本testing,其中显示了更广泛的选项,使用两个视图:

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> 

也可以看看:

  • JSF闪存文档
  • 在用户手动重新加载视图时保持Flash参数
Interesting Posts