在JSF表单提交上保留GET请求查询字符串参数

时间:2013-07-18 21:26:45

标签: jsf jsf-2 navigation http-request-parameters

我有3页:

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

agreement.xhtml需要正确加载两个参数:serviceIdsite。因此,普通网址如下所示:/app/agreement.xhtml?site=US&serviceId=AABBCC

我在agreement.xhtml

上有这个按钮
<h:form>
   <h:commandButton value="Generate License File" action="#{agreement.generateMethod}" />   
</h:form>

@RequestScoped bean #{agreement}有这种方法:

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

我需要在点击时执行generateMethod()方法,完成后,用户将被重定向到generated.xhtml页面。发生的事情是,点击后,页面浏览器会将用户发送到/app/agreement.xhtml,由于它没有发送参数siteserviceId,因此会崩溃。

我尝试让generateMethod()返回"generated?faces-redirect=true",但仍然没有。有什么想法吗?

2 个答案:

答案 0 :(得分:32)

您的具体问题是由于JSF <h:form>默认提交到当前请求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>不合适,因为当表单上发生转换或验证错误时,它会混淆地丢失其值。

要让它们重新显示在网址中,您需要<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,以便在打开带有表单的页面和提交表单之间保持这些参数,同样也可以验证错误。否则,当坚持@RequestScoped bean时,您应该在命令组件中将它们保留为<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>替换<o:form>,如下所示(另请参阅showcase example):

<o:form includeRequestParams="true">

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

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

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

public String generateMethod() {
    // ...

    return "generated";
}

或者,如果您使用的是漂亮的URL(例如PrettyFaces或FacesViews),或者可能是本土的并且打算提交到浏览器地址栏中显示的完全相同的URL,那么您可以使用{{1}而不是。

useRequestURI

另见:

答案 1 :(得分:5)

您的generateMethod必须返回

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

您甚至可以将&amp;替换为&,但可以在xhtml中将其撤消。

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>