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

我有3页:

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

agreement.xhtml需要两个参数来正确加载: serviceIdsite 。 所以,一个普通的url看起来像这样: /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" ,但还是什么都没有。 有任何想法吗?

您的具体问题是由于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>是不合适的,因为在表单上发生转换或验证错误时,它会令人迷惑地失去它的值。

为了让它们重新出现在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 ,以便在打开页面和表单并提交表单(也是验证错误)之间保持这些参数。 否则,坚持使用@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 ,那么您也可以用<o:form>替换<h:form> ,如下所示(另请参见showcase示例 ):

 <o:form includeRequestParams="true"> 

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

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

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

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

或者,如果您使用PrettyFaces或FacesView等“漂亮的网址”库,或者可能是本地发布的并打算提交到与浏览器地址栏中显示的网址完全相同的网址,则可以使用useRequestURI代替。

 <o:form useRequestURI="true"> 

也可以看看:

  • 什么可以使用<f:元数据>,<f:viewParam>和<f:viewAction>?
  • 如何在JSF中导航? 如何使URL反映当前页面(而不是以前的页面)

你的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>