11

有没有办法使用 h:outputLink、其他 JSF 标记或代码创建带有请求参数的非面孔请求 (HTTP GET) 的 html 链接?

例如我有以下导航规则

<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。

4

4 回答 4

12

这是一个有趣的想法。我很想知道它在实践中的表现如何。

获取导航规则

导航由NavigationHandler处理。掌握 NavigationHandler 并不困难,但 API 不会公开它使用的规则。

如我所见,您可以:

  1. 在初始化时解析 faces-config.xml 并将规则存储在应用程序上下文中(简单
  2. 实现您自己的 NavigationHandler 忽略 faces-config.xml 中的规则或用您自己的规则文件补充它们并以某种方式公开其规则集(可行,但需要一些工作
  3. 模拟你自己的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 。

于 2008-09-26T15:00:42.967 回答
3

尝试使用 PrettyFaces?它是一个开源 JSF 扩展,专门设计用于使带有 GET 请求的可收藏 JSF 页面/JSF 成为可能。

PrettyFaces - JSF / JSF2 的 SEO、动态参数、书签和导航

于 2009-11-03T19:18:53.813 回答
0

你考虑过表格吗?

<h:form>
    <h:commandLink value="Click to see the message" action="#{handler.outcome}" />
    <h:inputHidden id="msgId" value="#{bean.msgId}"/>
</h:form>
于 2008-09-26T13:52:30.540 回答
0

您可以使用带有嵌套参数标签的 commandLink。这和上面说的 hubbardr 基本一样:

<h:form>
  <h:commandLink value="click here" action="${handler.outcome}">
    <f:param name="msgId" value="${bean.id}" />
  </h:commandLink>
</h:form>

然后在你的backing bean中你需要做:

Map requestMap = FacesContext.getCurrentInstance()
                 .getExternalContext().getRequestParameterMap();
String msgId = (String) requestMap.get("msgId");

然后做任何你需要做的事情。

于 2008-10-02T18:46:34.073 回答