如何使用JSF和导航规则创建带参数的GET请求?

Pan*_*ros 10 java navigation jsf redirect

有没有办法使用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>
Run Code Online (Sandbox Code Playgroud)

在我的页面中,我想输出以下HTML代码:

<a href="/showMessage.jsf?msg=23">click to see the message</a>
Run Code Online (Sandbox Code Playgroud)

我可以只写在页面的HTML代码,但我想使用的导航规则,以在单个配置文件中定义的所有URL.

McD*_*ell 11

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

获取导航规则

导航由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>
Run Code Online (Sandbox Code Playgroud)

资源:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

得到

对于GET请求,您可以使用UIParameters设置值,并让渲染器构建参数列表.

<h:outputLink value="#{navBean.urlLink}">
    <f:param name="foo" value="#{navBean.value}" />
    <h:outputText value="get" />
</h:outputLink>
Run Code Online (Sandbox Code Playgroud)

POST

如果要在POST操作期间将URL设置为视图,可以使用操作中的重定向(由按钮或commandLink调用)来执行此操作.

<h:commandLink id="myCommandLink" action="#{navBean.invokeRedirect}">
    <h:outputText value="post" />
</h:commandLink>
Run Code Online (Sandbox Code Playgroud)

笔记

请注意,ExternalContext.encodeActionURL用于对字符串进行编码.这是生成可跨上下文(portlet等)移植的代码的好习惯.如果要编码图像或下载文件的链接,则可以使用encodeResourceURL.

  • 请注意,我在JSF2/JEE6出现之前写了这个答案.JSF2增加了对视图参数的支持.任何坚持使用JSF1.2/JEE5的人都应该考虑使用Seam. (2认同)