您的具体问题是因为 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 工作,您需要在both 源页面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>
基本上就是这样。这将生成一个包含当前查询字符串的<form action>。
<form action="/app/agreement.xhtml?site=US&serviceId=AABBCC" ...>
然后,这些请求参数仅在表单提交的请求参数映射中可用。您不需要额外的元数据/视图参数,也不需要发送重定向,如有必要,您的 bean 可以保留@RequestScoped。
public String generateMethod() {
// ...
return "generated";
}
另见: