每个请求都会重新创建复合组件中的支持bean [英] Backing bean in composite component is recreated on every request

查看:101
本文介绍了每个请求都会重新创建复合组件中的支持bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个变量userId和name。当我点击例如SHOW USERID按钮时它工作正常并设置renderUserId = true并用render显示它,但是如果我点击另一个SHOW按钮,那么Bean重建并且我松了renderUserId = true,它变成false和renderName = true所以它显示ok,但USERID是隐藏的。

I have two variables "userId" and "name". When I click for example the "SHOW USERID" button it works fine and sets "renderUserId=true" and it shows it with the "render", but then if I click the other "SHOW" button, the Bean is reconstruct and I loose the "renderUserId=true" and it becomes "false" and "renderName=true" so it shows ok, but the USERID is hidden.

我的问题是,怎么能我在渲染xhtml时避免丢失bean值?

My question is, how can I avoid loosing the bean values when I render the xhtml?

这是对我的代码的简单模拟。

This is a simple simulation of my code.

注意:如果我在h:commandButton中使用actionListener而不是f:setPropertyActionListener,我会得到相同的结果,那么bean就会重建

NOTE: if I use "actionListener" instead of "f:setPropertyActionListener" in the "h:commandButton" I have the same result, the bean is reconstruct

example.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:cc="http://java.sun.com/jsf/composite">

    <cc:interface componentType="com.bean.ExampleBean">
        <cc:attribute name="userId" type="java.lang.Integer"/>
        <cc:attribute name="name" type="java.lang.String"/>
    </cc:interface>

    <cc:implementation>

        <h:panelGrid id="example_panel" columns="1" width="100%">

            <h:outputText value="USERID: #{cc.attrs.userId}" rendered="#{!cc.attrs.renderUserId}"/>

            <a4j:commandButton value="SHOW USERID" render="example_panel"
                rendered="#{!cc.attrs.renderUserId}">
                <f:setPropertyActionListener value="#{true}"
                    target="#{cc.attrs.renderUserId}"/>
            </a4j:commandButton>                
            <a4j:commandButton value="HIDE USERID" render="example_panel"
                rendered="#{cc.attrs.renderUserId}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderUserId}"/>
            </a4j:commandButton>                


            <h:outputText value="NAME: #{cc.attrs.name}" rendered="#{!cc.attrs.renderName}"/>

            <a4j:commandButton value="SHOW NAME" render="example_panel"
                rendered="#{!cc.attrs.renderName}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderName}"/>
            </a4j:commandButton>                
            <a4j:commandButton value="HIDE NAME" render="example_panel"
                rendered="#{cc.attrs.renderName}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderName}"/>
            </a4j:commandButton>                


        </h:panelGrid>

    </cc:implementation>

</ui:composition>

ExampleBean.java

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;


@FacesComponent("com.bean.ExampleBean")
public class ExampleBean extends UINamingContainer {

    private Integer userId;
    private String name;

    private boolean renderUserId;
    private boolean renderName;

}


推荐答案

有一个主要的误解就在这里。那不是支持豆。这是一个支持组件。

There's a major misconception going here. That's not a backing bean. That's a backing component.

JSF UI组件实例不是视图范围,而是请求范围。它们在渲染响应结束时被破坏(在将状态保存到JSF视图状态之后)并在视图构建期间重新创建(并且它们的状态从JSF视图状态恢复)。

JSF UI component instances are not view scoped, instead they are request scoped. They are destroyed by end of render response (after having saved their state into JSF view state) and recreated during view build time (and their state is restored from JSF view state).

您已将有状态属性指定为组件的实例变量。这个不对。您应该明确地将它们存储在JSF状态中。正确的方法是让getter和setter委托给 UIComponent#getStateHelper() 。声明为< cc:attribute> 的任何属性都已隐式执行此操作。您绝对不需要将它们重新声明为支持组件的实例变量。

You've assigned the stateful properties as instance variables of the component. This is not right. You should be explicitly storing them in the JSF state. The correct approach for that is to let the getter and setter delegate to UIComponent#getStateHelper(). Any attributes which are declared as <cc:attribute> already implicitly do that. You do absolutely not need to redeclare them as instance variables of the backing component.

那些未声明为< cc:attribute> 的布尔值必须重新实现,如下所示:

Those booleans which are not declared as <cc:attribute> must be reimplemented like follows:

public Boolean getRenderUserId() {
    return (Boolean) getStateHelper().eval("renderUserId", Boolean.FALSE);
}

public void setRenderUserId(Boolean renderUserId) {
    getStateHelper().put("renderUserId", renderUserId);
}

在你的行动(听众)方法中,只需调用因此,setRenderUserId(true)

In your action(listener) method, just invoke setRenderUserId(true) accordingly.

不要忘记相应地修复EL表达式:

Don't forget to fix the EL expressions accordingly:

#{cc.renderUserId} 



参见:



查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆