如何使用JSF和导航规则创建带有参数的GET请求?
有没有一种方法可以使用h:outputLink,其他JSF标签或者代码来创建html链接,以创建带有请求参数的非人脸请求(HTTP GET)?
例如,我有以下导航规则
<navigation-rule> <navigation-case> <from-outcome>showMessage</from-outcome> <to-view-id>/showMessage.jsf</to-view-id> <redirect/> </navigation-case> </navigation-rule>
在我的页面中,我想输出以下html代码:
<a href="/showMessage.jsf?msg=23">click to see the message</a>
我可以只在页面中编写html代码,但是我想使用导航规则,以便将所有url定义在单个可配置文件中。
解决方案
我们考虑过表格吗?
<h:form> <h:commandLink value="Click to see the message" action="#{handler.outcome}" /> <h:inputHidden id="msgId" value="#{bean.msgId}"/> </h:form>
这是一个有趣的想法。我很想知道它在实践中如何成功。
获取导航规则
导航由NavigationHandler处理。掌握NavigationHandler并不困难,但是API不会公开其使用的规则。
如我所见,我们可以:
- 在初始化时解析faces-config.xml并将规则存储在应用程序上下文中(简单)
- 实现自己的NavigationHandler,它会忽略faces-config.xml中的规则或者使用我们自己的规则文件对其进行补充,并以某种方式公开其规则集(可行,但需要一些工作)
- 模拟我们自己的FacesContext并将其传递给现有的导航处理程序(很难使两个FacesContext对象共存于同一线程中并且效率极低)
现在,我们还有另一个问题。我们将在哪里保留映射以查找视图?将它们硬编码在bean中?
使用导航规则
临时而言,我可以想到两种从后端构造包含参数的URL的方法。两者都涉及定义某种bean。
<managed-bean> <managed-bean-name>navBean</managed-bean-name> <managed-bean-class>foo.NavBean</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean>
来源:
package foo; import java.io.IOException; import java.io.Serializable; import java.net.URLEncoder; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; public class NavBean implements Serializable { private String getView() { String viewId = "/showMessage.faces"; // or look this up somewhere return viewId; } /** * Regular link to page */ public String getUrlLink() { FacesContext context = FacesContext.getCurrentInstance(); ExternalContext extContext = context.getExternalContext(); String viewId = getView(); String navUrl = context.getExternalContext().encodeActionURL( extContext.getRequestContextPath() + viewId); return navUrl; } /** * Just some value */ public String getValue() { return "" + System.currentTimeMillis(); } /** * Invoked by action */ public String invokeRedirect() { FacesContext context = FacesContext.getCurrentInstance(); ExternalContext extContext = context.getExternalContext(); String viewId = getView(); try { String charEncoding = extContext.getRequestCharacterEncoding(); String name = URLEncoder.encode("foo", charEncoding); String value = URLEncoder.encode(getValue(), charEncoding); viewId = extContext.getRequestContextPath() + viewId + '?' + name + "=" + value; String urlLink = context.getExternalContext().encodeActionURL( viewId); extContext.redirect(urlLink); } catch (IOException e) { extContext.log(getClass().getName() + ".invokeRedirect", e); } return null; } }
得到
对于GET请求,可以使用UIParameters设置值,并让渲染器构建参数列表。
<h:outputLink value="#{navBean.urlLink}"> <f:param name="foo" value="#{navBean.value}" /> <h:outputText value="get" /> </h:outputLink>
邮政
如果要在POST操作期间将URL设置为视图,则可以使用操作中的重定向(由按钮或者commandLink调用)来实现。
<h:commandLink id="myCommandLink" action="#{navBean.invokeRedirect}"> <h:outputText value="post" /> </h:commandLink>
笔记
请注意,ExternalContext.encodeActionURL用于对字符串进行编码。这是生成可跨上下文(portlet等)移植的代码的良好实践。如果我们要编码到图像或者下载文件的链接,则应使用encodeResourceURL。
我们可以将CommandLink与嵌套的param标签一起使用。这基本上与上述hubbardr相同:
<h:form> <h:commandLink value="click here" action="${handler.outcome}"> <f:param name="msgId" value="${bean.id}" /> </h:commandLink> </h:form>
然后在后备豆中,我们需要执行以下操作:
Map requestMap = FacesContext.getCurrentInstance() .getExternalContext().getRequestParameterMap(); String msgId = (String) requestMap.get("msgId");
然后执行我们需要做的任何事情。
尝试过使用PrettyFaces?这是一个开放源代码的JSF扩展,专门用于使可添加书签的JSF页面/具有GET请求的JSF成为可能。
用于JSF / JSF2的PrettyFaces SEO,动态参数,书签和导航