首页 文章

如何在Ajax调用或重新加载后将对象保留在JSF Flash Scope上?

提问于
浏览
3

我有一个'大'项目,大表和很多关系......所以在我的表单中,我有几个选项卡,一些对话框和许多PrimeFaces commandButtons来管理所有带有Ajax请求的CRUD .

xhtml结构是这样的:

<ui:define name="content">
<h:body>
    <p:growl id="growl"/>
    <h:form id="formCars" enctype="multipart/form-data">
        <p:tabView id="formTabView" scrollable="true" >
            <p:tab title="Tab1">
                <ui:include src="tabOne/tabOne.xhtml" />
            </p:tab>
            <p:tab title="Tab2">...</p:tab>
            ...
            <p:tab title="Tab8">...</p:tab>
        </p:tabView>
        
<div align="center"> <p:commandButton id="cmdSave" value="Save" action="#{controllerMB.save}" icon="ui-icon-disk" update="@form :growl" process="@form @this" validateClient="true" /> </div> </h:form> <p:dialog header="Car Color" id="modalCarColor" widgetVar="modalCarColor" appendToBody="true" modal="true" height="500" width="700" dynamic="true" closeOnEscape="true" > <p:ajax event="close" listener="#{controllerMB.closeModalCarColor}" update="@this,:formCarColor"/> <h:form id="formCarColor"> <ui:include src="tabTwo/carColor/carColor.xhtml" /> </h:form> </p:dialog> <p:dialog header="Car Size" ...> <p:ajax event="close" .../> <h:form id="formCarColor">...</h:form> </p:dialog> </h:body> </ui:define>

它运行完美......问题是当我尝试重新加载页面时...我设法通过使用将主要对象保留在闪存上

FacesContext.getCurrentInstance().getExternalContext().getFlash().keep(key)

在@ViewScoped控制器的@PostConstruct上 . 如果我访问页面而不接触ajax按钮,我可以重新加载页面而不会有问题......但是,如果我触摸任何导致和ajax请求的东西,JSF Flash Scopre会丢失主要对象,因此我不能重新加载页面 .

我的控制器是这样构建的:

@ManagedBean(name="controllerMB")
@ViewScoped
public class ControllerMB implements Serializable{
    // attributes
    // ----------
    @PostConstruct
    public void init(){

        if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
            car = (Car) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("car");
            FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
        }
        if(car==null) { 
            redirect_back();
            return;
        }

        // attributes initialization and form preparation
        // -----
    }

    // methods
    // ----------

}

“汽车”作为主要对象只是一个例子 .

这有什么解决方案或解决方法吗?

我希望在“意外重新加载”之后保持状态,但是它不适用于Flash .

此外,是否可以从浏览器捕获/处理重新加载事件(可能使用js)?我的意思是,然后我可以在重新加载之前处理我的主对象中的表单 .

我在我的项目中使用PrimeFaces 5.3,JSF 2,Maven,Tomcat 7和Java 7 .

谢谢大家 .


Edit 1: 在尝试用户NightEagle提到的解决方案之后, almost 工作了...我修改了代码:

<ui:composition ....>
    <f:metadata>
      <f:event type="preRenderView" listener="#{controllerMB.preRender}"/>
    </f:metadata>
    <ui:define name="title">...</ui:define>
    <ui:define name="header">...</ui:define>
    <ui:define name="content">...</ui:define>
</ui:composition>

public void preRender()
{
    System.out.print("PRE-RENDER ");
    if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
        System.out.println("KEEP");
        FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
    } else {
        System.out.println("PUT");
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("car",car);
    }
}

奇怪的是,第一个ajax调用很好,在第二个之后......它开始弹出JSF1095错误 .

一些对话框开放后的输出:

PRE-RENDER PUT
PRE-RENDER KEEP
PRE-RENDER KEEP
Jul 14, 2017 11:43:59 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash.  Any values stored to the flash will not be available on the next request.
PRE-RENDER PUT
Jul 14, 2017 11:44:00 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash.  Any values stored to the flash will not be available on the next request.
PRE-RENDER PUT
Jul 14, 2017 11:44:04 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash.  Any values stored to the flash will not be available on the next request.

提前谢谢大家,仍然找到解决方案 .

1 回答

  • 2

    我想我知道如何解决它(它在我的项目中帮助了我)

    <f:metadata>
      <f:event type="preRenderView" listener="#{myBean.preRender}"/>
    </f:metadata>
    

    支持 beans :

    public class MyBean
    {
        @PostConstruct
        public void init(){
            if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
                car = (Car) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("car");
                FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
            }
        }
    
        public void preRender()
        {
            if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
                FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
            }
        }
    }
    

    "The preRenderView event is invoked on every HTTP request (yes, this also includes ajax requests!)."(c)https://stackoverflow.com/a/9844616/3163475

相关问题