JSF commandButton'奇怪'的行为

时间:2011-12-21 15:06:23

标签: jsf datatable action

对于以下案例,我会非常高兴得到一个很好的解释。

这是一个简单的JSF,有两种形式和文本输出:

<h:body>
<h:form>
<h:commandButton value="Go" action="#{wierdBean.doWierdStuff}"/>
</h:form>

<h:form>
<h:dataTable value="#{wierdBean.pages}" var="page">
<h:column>
<h:commandButton value="the same go action?" action="#{wierdBean.doWierdStuff}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>

<h:dataTable value="#{wierdBean.pages}" var="page">
<h:column>
<h:outputText value="#{page}"/>
</h:column>
</h:dataTable>
顶部的“Go”按钮应该做同样的事情 作为'同样的行动?'的按钮。

支持WierdBean是:

public class WierdBean implements Serializable {

private int buttonsCount;

public WierdBean() {
System.out.println("WierdBean()");
}

@PostConstruct
public void postConstruct() {
System.out.println("postConstruct()");
}

public Integer[] getPages() {
System.out.print("getPages() buttonsCount(): " + buttonsCount);
Integer[] pages = new Integer[buttonsCount];
for (int i = 0; i < pages.length; i++) {
pages[i] = new Integer(i);
}
return pages;
}

public String doWierdStuff() {
System.out.println("doWierdStuff()");
buttonsCount = 2;
return "wierd";
}
}

当我进入页面时,我得到:

INFO: WierdBean()
INFO: postConstruct()
INFO: getPages() buttonsCount(): 0 (16 times)

我只看到了“开始”按钮。这是可以理解的。

按下“开始”按钮后,我得到:

INFO: WierdBean() 
INFO: postConstruct() 
INFO: getPages() buttonsCount(): 0 (19 times) 
INFO: doWierdStuff() 
INFO: getPages() buttonsCount(): 2 (16 times)

很好,doWierdStuff被调用然后我得到2'相同的go动作'按钮和2个文本输出。 没关系。

然而,当我按下任何应该执行的“相同动作”按钮时 与“Go”按钮相同 - 调用doWierdStuff方法 - 我得到:

INFO: WierdBean() 
INFO: postConstruct() 
INFO: getPages() buttonsCount(): 0 (44 times)

只有“开始”按钮可见。

为什么?

1 个答案:

答案 0 :(得分:0)

你的具体问题是双重的:bean明显是请求作用域而不是视图作用域你在getter方法中做业务工作而不是(post)构造函数或(action)监听器方法。

请求范围的bean在每个单独的请求上重新创建,并且不会在同一视图上的后续请求中重用。所有属性(如buttonsCount)都会重新初始化为默认值。单击数据表中的命令链接/按钮时,需要确保在初始请求中保留完全相同的数据模型。如果不这样做,JSF将无法找到要调用的操作。只要您通过返回nullvoid与同一视图进行交互,bean就需要生存。这可以通过@ViewScoped将bean放在视图范围内(或者当你仍然使用Tomahawk的<t:saveState>组件时过时的JSF 1.x)来实现。

支持bean getter方法应该只返回事先已经准备好的数据,而不是准备数据本身。 getter方法应该只是数据的访问点。这是因为在请求 - 响应周期中可以多次调用getter方法,尤其是在UIData组件和/或rendered属性中引用时。

另见: