使用请求范围的bean函数作为JSF中临时呈现按钮的操作

hub*_*bba 5 java jsf

我在JSF中有以下基本(也许是愚蠢的)理解问题:

有一个JSF页面"testPage.xhtml":

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">

<f:view>
<h:body>
<h:form>
    <h:commandLink id="B1" value="B1" action="#{testBean.ctrl}"/>

    <h:commandLink id="B2" value="B2" action="#{testBean.ctrl}"
            rendered="#{testBean.renderB2}"/>
</h:form>
</h:body>
</f:view>
</html>
Run Code Online (Sandbox Code Playgroud)

还有一个支持bean"TestBean.java":

package test;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name="testBean")
@RequestScoped
public class TestBean implements Serializable {

    public static final long serialVersionUID = 1L;

    private boolean renderB2 = false;

    public String ctrl() {
            setRenderB2(true);

            System.out.println("ctrl() is called.");

            return null;
    }

    public boolean getRenderB2() {
            return renderB2;
    }

    public void setRenderB2(boolean renderB2) {
            this.renderB2 = renderB2;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这两个链接都有TestBean.ctrl()行动.

首先只B1渲染.单击B1会导致执行TestBean.ctrl()并且B2也会呈现.

但是,单击B2然后就没有执行TestBean.ctrl().

这是我的问题:为什么点击时不执行动作方法B2

可能是因为B2没有再次渲染.但是为什么这会阻止动作方法的执行(由之前渲染的B2链接调用)?

Bal*_*usC 6

这是因为rendered在表单提交的应用请求值阶段期间再次重新评估该属性.如果在该点未呈现UIInputUICommand组件,则JSF将不应用该组件的请求值.即UIInput组件的模型值将不会更新,并且UICommand不会调用组件的操作.

因为您的bean是请求范围的,所以它会在显示表单的响应结束时被删除,并且通过表单提交的请求开始创建一个全新的表单.

您必须保留负责该rendered属性的任何请求范围属性.最简单的方法是通过标记bean @ViewScoped并确保返回nullvoid从应该回发到同一视图的操作方法将bean放在视图范围中.