所以我有这个非常小的JSF示例:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Index</title>
</h:head>
<h:body>
<h:form>
<h:commandButton action="#{reqScopedBackingBean.foo()}" value="Submit"/>
</h:form>
</h:body>
</html>
和foo的实现如下:
package biz.tugay.jsftags;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@RequestScoped
public class ReqScopedBackingBean {
public String foo() {
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("message", "Success!!");
return "hello?faces-redirect=true";
}
}
,最后hello.xhtml
如下:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Hello</title>
</h:head>
<h:body>
<h:outputText value="#{flash.keep.message}"/>
</h:body>
</html>
在上面的例子中,当我点击Submit时,我将被重定向到hello.xhtml,并看到"Success!!"文本。当我刷新页面时,我仍然会看到消息,因为我调用了keep方法,如下所示:
#{flash.keep.message}
现在看另一个例子:
index.xhtml和ReqScopedBackingBean是相同的,但是这次hello.xhtml如下:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Hello</title>
</h:head>
<h:body>
#{otherBean.pullValuesFromFlash()}
<h:outputText value="#{otherBean.message}"/>
</h:body>
</html>
和OtherBean.java
如下:
@ManagedBean
@RequestScoped
public class OtherBean {
private String message;
public void pullValuesFromFlash() {
final Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.keep("message");
final String message = (String) flash.get("message");
setMessage(message);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
我期望的行为是相同的第一个例子。但是,当我使用hello.xhtml时,我将看不到成功消息。但是,如果我注释掉这行:
// flash.keep("message");
则会显示消息(但是在hello.xhtml上刷新不会像第一个示例那样重新显示成功消息)。
我的问题是,这里有什么区别?
#{flash.keep.message}
与
不同flash.keep("message");
final String message = (String) flash.get("message");
?
你已经击中了Flash#keep()
的Mojarra bug。基本上,Mojarra没有必要在将条目放入下一个flash作用域之前将其从当前flash作用域中移除。
如果按照下面的顺序重新排列逻辑,它将工作。
public void pullValuesFromFlash() {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
String message = (String) flash.get("message");
flash.keep("message");
setMessage(message);
}
我已经按照第4167期修复了这个错误。
与具体问题无关的,这些<h:outputText>
s是不必要的。您可以安全地删除它们以减少样板文件。参见是否建议使用h:outputText来处理所有内容?