22

I have 3 pages:

  • main.xhtml
  • agreement.xhtml
  • generated.xhtml

The agreement.xhtml needs two parameters to load correctly: serviceId and site. So, a normal url looks like this: /app/agreement.xhtml?site=US&serviceId=AABBCC.

I have this button on agreement.xhtml

<h:form>
   <h:commandButton value="Generate License File" action="#{agreement.generateMethod}" />   
</h:form>

The @RequestScoped bean #{agreement} has this method:

public String generateMethod(){
    .......
    return "generated";
}

I need that, on click, the generateMethod() method is executed, and after it's done, the user is redirected to the generated.xhtml page. What's happening is that, on click, the page browser sends the user to /app/agreement.xhtml and, since it's not sending the parameters site and serviceId, it crashes.

I tried making the generateMethod() return a "generated?faces-redirect=true", but still nothing. Any ideas?

4

2 回答 2

39

您的具体问题是由于<h:form>默认情况下 JSF 提交到当前请求 URL 而没有任何查询字符串。仔细查看生成的 HTML 输出,您会看到

<form action="/app/agreement.xhtml" ...>

因此,您明确需要自己包含这些请求参数。有几种方法可以解决这个问题。如果您没有发送重定向,那么您可以将它们作为隐藏输入添加到 JSF 表单中。

<h:form>
    <input type="hidden" name="site" value="#{param.site}" />
    <input type="hidden" name="site" value="#{param.serviceId}" />
    ...
</h:form>

只是,这些参数不会重新出现在浏览器地址栏中的 URL 中。如果您只在同一页面上使用 ajax,这不是问题。顺便说一句,这<h:inputHidden>是不合适的,因为当表单上发生转换或验证错误时,它会混淆地失去其价值。

为了让它们重新出现在 URL 中,您需要<f:viewParam>includeViewParams. 为了开始includeViewParams工作,您需要在源页面中声明以下内容agreement.xhtml...

<f:metadata>
    <f:viewParam name="site" value="#{agreement.site}" />
    <f:viewParam name="serviceId" value="#{agreement.serviceId}" />
</f:metadata>

...目标页面generated.xhtml

<f:metadata>
    <f:viewParam name="site" value="#{generated.site}" />
    <f:viewParam name="serviceId" value="#{generated.serviceId}" />
</f:metadata>

现在您可以发送包含视图参数的重定向,如下所示:

public String generateMethod() {
    // ...

    return "generated?faces-redirect=true&includeViewParams=true";
}

请注意,bean 应该是@ViewScoped为了使这些参数在打开带有表单的页面和提交表单之间保持活动状态,以及验证错误。否则,当坚持使用@RequestScopedbean 时,您应该像<f:param>在命令组件中一样保留它们:

<h:commandButton ...>
    <f:param name="site" value="#{generated.site}" />
    <f:param name="serviceId" value="#{generated.serviceId}" />
</h:commandButton>

没有办法为<f:ajax>内部输入组件设置它们,你的 bean 应该真的是@ViewScoped.


或者,如果您碰巧已经使用 JSF 实用程序库OmniFaces,那么您也可以按如下方式替换<h:form>by (另请参见展示示例):<o:form>

<o:form>

基本上就是这样。这将生成一个<form action>包含当前查询字符串的内容。

<form action="/app/agreement.xhtml?site=US&serviceId=AABBCC" ...>

然后,这些请求参数仅在表单提交的请求参数映射中可用。您不需要额外的元数据/视图参数,也不需要发送重定向@RequestScoped,如有必要,您的 bean 可以保留。

public String generateMethod() {
    // ...

    return "generated";
}

也可以看看:

于 2013-07-19T11:59:38.177 回答
6

generateMethod将不得不返回

return "generated?site=US&amp;serviceId=AABBCC&amp;faces-redirect=true";

您甚至可以在您的 xhtml 中替换&amp;&但将其转义。

在您中,您可以像这样generated.xhtml捕获正在传递的参数<f:viewParam>

<f:metadata>
    <f:viewParam name="site" value="#{yourBean.site}"/><!--Make sure you have a setter-->
    <f:viewParam name="serviceId" value="#{yourBean.serviceId}"/><!--Make sure you have a setter-
</f:metadata>
<h:head>
于 2013-07-18T23:16:10.517 回答