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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/138617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:45:59  来源:igfitidea点击:

How to create a GET request with parameters, using JSF and navigation-rules?

javajsfredirectnavigation

提问by Panagiotis Korros

Is there a way to create an html link using h:outputLink, other JSF tag or code to create a non faces request (HTTP GET) with request parameters?

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

For example I have the following navigation-rule

例如我有以下导航规则

<navigation-rule>
    <navigation-case>
        <from-outcome>showMessage</from-outcome>
        <to-view-id>/showMessage.jsf</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

In my page I would like to output the following html code:

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

<a href="/showMessage.jsf?msg=23">click to see the message</a>

I could just write the html code in the page, but I want to use the navigation rule in order to have all the urls defined in a single configurable file.

我可以只在页面中编写 html 代码,但我想使用导航规则,以便在单个可配置文件中定义所有 url。

采纳答案by McDowell

This is an interesting idea. I'd be curious to know how it pans out in practice.

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

Getting the navigation rules

获取导航规则

Navigation is handled by the NavigationHandler. Getting hold of the NavigationHandler isn't difficult, but the API does not expose the rules it uses.

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

As I see it, you can:

在我看来,你可以:

  1. parse faces-config.xml on initialization and store the rules in the application context (easy)
  2. implement your own NavigationHandler that ignores the rules in faces-config.xml or supplements them with your own rules file and exposes its ruleset somehow (workable, but takes a bit of work)
  3. mock your own FacesContextand pass it to the existing navigation handler (really difficult to make two FacesContext object coexist in same thread and extremely inefficient)
  1. 在初始化时解析 faces-config.xml 并将规则存储在应用程序上下文中(简单
  2. 实现您自己的 NavigationHandler 忽略 faces-config.xml 中的规则或用您自己的规则文件补充它们并以某种方式公开其规则集(可行,但需要一些工作
  3. 模拟你自己的FacesContext并将其传递给现有的导航处理程序(很难让两个 FacesContext 对象共存于同一个线程中,而且效率极低

Now, you have another problem too. Where are you going to keep the mappings to look up the views? Hard-code them in the beans?

现在,您还有另一个问题。您将在哪里保留映射以查找视图?将它们硬编码在 bean 中?

Using the navigation rules

使用导航规则

Off hand, I can think of two ways you could construct parameter-containing URLs from the back-end. Both involve defining a bean of some kind.

顺便说一下,我可以想到两种从后端构造包含参数的 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>

Source:

来源:

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

得到

For a GET request, you can use the UIParameters to set the values and let the renderer build the parameter list.

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

<h:outputLink value="#{navBean.urlLink}">
    <f:param name="foo" value="#{navBean.value}" />
    <h:outputText value="get" />
</h:outputLink>

POST

邮政

If you want to set the URL to a view during a POST action, you can do it using a redirect in an action (invoked by a button or commandLink).

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

<h:commandLink id="myCommandLink" action="#{navBean.invokeRedirect}">
    <h:outputText value="post" />
</h:commandLink>

Notes

笔记

Note that ExternalContext.encodeActionURLis used to encode the string. This is good practice for producing code that is portable across contexts (portlets, etcetera). You would use encodeResourceURLif you were encoding a link to an image or download file.

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

回答by hubbardr

Have you considered a form?

你考虑过表格吗?

<h:form>
    <h:commandLink value="Click to see the message" action="#{handler.outcome}" />
    <h:inputHidden id="msgId" value="#{bean.msgId}"/>
</h:form>

回答by Ian McLaird

You could use a commandLink with nested param tags. This is basically the same as hubbardr said above:

您可以使用带有嵌套参数标签的 commandLink。这与上面 hubbardr 所说的基本相同:

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

Then in your backing bean you need to do:

然后在您的支持 bean 中,您需要执行以下操作:

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

And then do whatever you need to do.

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

回答by Lincoln

Tried using PrettyFaces? It's an open-source JSF extension designed specifically to make bookmarkable JSF pages / JSF with GET requests possible.

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

PrettyFaces - SEO, Dynamic Parameters, Bookmarks and Navigation for JSF / JSF2

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