6

f:param很好用h:link,但不能用p:commandLinkor h:commandLink

例如,我有两个页面test_first.xhtmltest_second.xhtml,以及一个支持 java bean TestBean.java

我开始跑步test_first.xhtml

如果我单击link1,这是一个h:link,页面将重定向到test_second.xhtml。借助f:param, 浏览器的地址栏就会显示出来.../test_second.xhtml?id=1。在那个页面上,testBean.userId被打印出来。

如果我单击link2link3,页面将重定向到test_second.xhtml。但是,地址栏只显示.../test_second.xhtml,没有?id=#!并且testBean.userId不会在该页面上打印。

我怎样才能commandLink工作f:param?有时我希望链接不要重定向到另一个页面,而是根据数据调用 bean 的一些方法。

test_first.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head/>
<h:body>
<h:form>
    <h:link value="link1" outcome="test_second" >
        <f:param name="id" value="1"/>
    </h:link>
    <br/><br/>
    <h:commandLink value="link2" action="test_second?faces-redirect=true" >
        <f:param name="id" value="2" />
    </h:commandLink>
    <br/><br/>
    <p:commandLink value="link3" action="test_second?faces-redirect=true">
        <f:param name="id" value="3" />
    </p:commandLink>
    <br/><br/>
</h:form>
</h:body>
</html>

test_second.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<f:metadata>
    <f:viewParam name="id" value="#{testBean.userId}" />
</f:metadata>
<h:head/>
<h:body>
<h:form>
    This is the second page.
    <h:outputText value="Selected id is #{testBean.userId}" />
    <h:commandButton value="Print page id" action="#{testBean.print()}" />
</h:form>
</h:body>
</html>

TestBean.java

@ManagedBean
@SessionScoped
public class TestBean implements Serializable{
    private Integer userId;

    public void print() {
        System.out.println(userId);
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}
4

2 回答 2

8

您误解了这两个标签的含义,即<h:link>and <h:commandLink>,因此,您也误解了<f:param>附加到这两个标签中的任何一个的含义。无论如何,在提问之前阅读文档以获得更多见解是值得的。

<h:link>呈现一个 HTML "a" 锚元素。组件的值呈现为锚文本,组件的结果用于确定“href”属性中呈现的目标 URL。任何子UIParameter组件都附加到字符串,以在渲染之前作为“href”属性的值作为查询参数输出......

<h:commandLink>呈现一个 HTML “a” 锚元素,单击时就像表单提交按钮* ...如果 disabled 属性不存在,或者它的值为 false。它将“#”呈现为“href”属性的值,将组件的当前值呈现为链接文本(如果已指定),*将功能上等同于以下内容的 JavaScript 呈现为“onclick”属性的值:

document.forms['CLIENT_ID']['hiddenFieldName'].value='CLIENT_ID';    
document.forms['CLIENT_ID']['PARAM1_NAME'].value='PARAM1_VALUE'; 
document.forms['CLIENT_ID']['PARAM2_NAME'].value='PARAM2_VALUE'; return false;
document.forms['CLIENT_ID'].submit()" 

其中hiddenFieldName,如上所述,CLIENT_ID 是 UICommand 组件的 clientId,PARAM _NAME和 PARAM _VALUE 分别是任何嵌套 UIParameter children 的名称和值

换句话说,<h:link>标签内嵌套<f:param>最终将作为生成 URL 的查询参数,而<h:commandLink>标签内嵌套<f:param>最终将作为具有给定值的请求参数。

虽然第一个很清楚,但第二个值得更好地阐述。要了解它的作用,请考虑如果我们从细节中抽象出来<h:commandLink>发送一个 POST 请求并将所有嵌套<f:param>标签作为请求参数附加。但如何处理它们取决于您,因为导航完全掌握在您手中

所以,第一个选项是设置一个硬编码的action属性,这个用例是可疑的,就像 in 一样action="second-page"你根本没有传递任何查询参数。将要做的是发布到相同的视图并转发到第二个而不采取任何操作。相当愚蠢的动作。

第二个选项是指定一个操作方法,例如 in action="#{bean.action}"。在这种情况下,您必须在提供的操作方法中处理导航,即从方法返回null/void以进行回发,或者将导航案例结果作为字符串返回以转发到指定的视图。至于您传递的请求参数,<f:param>它们将可通过标准 JSF 方式使用,例如@ManagedProperty("#{param.name}")在请求范围的 bean 上,或通过调用ExternalContext#getRequestParameterMap()任何范围的 bean,例如在 action 方法中,如 in String param = externalContext.getRequestParameterMap().get("name")。因此,现在您有了参数 in action 方法,您可以随意使用,只需遵守 URL 存在的一组规则。

有两件事值得一提。请记住,通过调用命令链接传递的请求参数将仅在同一请求中可用,因为您可能希望它能够在faces-redirect=true基本上触发另一个请求的情况下继续存在。如果需要,另一个选项是指定includeviewparams=true通过当前视图的参数,如另一个答案中所述。

于 2013-08-21T07:04:20.057 回答
2

您可以通过&直接在 action 属性处连接参数来做到这一点:

<p:commandLink value="link3" action="test_second?faces-redirect=true&id=3"/>

更新 1

您也可以考虑添加&includeViewParams=true. 这样,您的目标导航的视图参数将自动包含在内。

于 2013-08-21T05:58:47.450 回答