每个请求都会重新创建复合组件中的支持bean

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

我的问题是,当我渲染xhtml时,如何避免丢失bean值?

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

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

example.xhtml

                        

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; } 

这里有一个重大的误解。 那不是支持豆。 这是一个支持组件。

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

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

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

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

在您的action(侦听器)方法中,只需相应地调用setRenderUserId(true)

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

 #{cc.renderUserId} 

也可以看看:

  • JSF复合组件 – 尝试保存状态时的奇怪行为
  • 我们的复合组件维基页面
  • 具有多个输入字段的复合组件

您的FacesComponent没有保持状态,每次调用它都是一个新实例。 对于您的用例,您似乎应该至少使用具有视图范围的ManagedBean。 这意味着只要您在带有按钮的页面上,就会保留实例。