Как создать запрос GET с параметрами, используя JSF и навигационные правила?

Есть ли способ создать html-ссылку с помощью h: outputLink, другого тега или кода JSF для создания запроса без лиц (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-адреса были определены в одном настраиваемом файле.

Ответ 1

Это интересная идея. Мне было бы интересно узнать, как это происходит на практике.

Получение правил навигации

Навигация осуществляется с помощью NavigationHandler. Удержание NavigationHandler не сложно, но API не раскрывает правила, которые он использует.

Как я вижу, вы можете:

  • parse faces-config.xml при инициализации и хранении правил в контексте приложения (легко)
  • реализовать свой собственный NavigationHandler, который игнорирует правила в faces-config.xml или дополняет их собственным файлом правил и каким-то образом предоставляет свой набор правил (работоспособный, но требует немного работы).
  • mock your FacesContext и передать его существующему обработчику навигации (действительно сложно сделать два объекта FacesContext сосуществовать в одном потоке и чрезвычайно неэффективное)

Теперь у вас еще одна проблема. Где вы собираетесь хранить сопоставления для просмотра взглядов? Скопируйте их в beans?

Использование правил навигации

Сразу, я могу подумать о двух способах создания 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

Для запроса GET вы можете использовать UIParameters для установки значений и позволить рендереру построить список параметров.

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

POST

Если вы хотите установить URL-адрес для представления во время действия POST, вы можете сделать это, используя перенаправление в действии (вызванное кнопкой или командойLink).

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

Примечания

Обратите внимание, что ExternalContext.encodeActionURL используется для кодирования строки. Это хорошая практика для создания кода, который переносится через контексты (портлеты и т.д.). Вы бы использовали encodeResourceURL, если бы вы кодировали ссылку на изображение или файл загрузки.

Ответ 3

Вы считали форму?

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

Ответ 4

Вы можете использовать commandLink с вложенными тегами param. Это в основном то же самое, что и hubbardr, сказанное выше:

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

Затем в вашей поддержке bean вам нужно сделать:

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

И затем сделайте все, что вам нужно.