Сохранение параметров строки запроса запроса GET в форме JSF

У меня есть 3 страницы:

  • main.xhtml
  • agreement.xhtml
  • generated.xhtml

Для правильной загрузки agreement.xhtml нужны два параметра: serviceId и site. Итак, обычный url выглядит так: /app/agreement.xhtml?site=US&serviceId=AABBCC.

У меня есть эта кнопка на agreement.xhtml

<h:form>
   <h:commandButton value="Generate License File" action="#{agreement.generateMethod}" />   
</h:form>

@RequestScoped bean #{agreement} имеет этот метод:

public String generateMethod(){
    .......
    return "generated";
}

Мне нужно, что при щелчке выполняется метод generateMethod(), и после его завершения пользователь перенаправляется на страницу generated.xhtml. Дело в том, что при щелчке браузер страницы отправляет пользователя в /app/agreement.xhtml и, поскольку он не отправляет параметры site и serviceId, он сбой.

Я попытался сделать generateMethod() return a "generated?faces-redirect=true", но все равно ничего. Любые идеи?

Ответ 1

Ваша конкретная проблема вызвана тем, что JSF <h:form> отправляет по умолчанию текущий URL-адрес запроса без какой-либо строки запроса. Посмотрите ближе на сгенерированный вывод HTML, вы увидите

<form action="/app/agreement.xhtml" ...>

Таким образом, вам явно нужно будет включать эти параметры запроса самостоятельно. Существует несколько способов решить эту проблему. Если вы не отправляли перенаправление, вы можете просто добавить их как скрытые входы в форму JSF.

<h:form>
    <input type="hidden" name="site" value="#{param.site}" />
    <input type="hidden" name="site" value="#{param.serviceId}" />
    ...
</h:form>

Только эти параметры не появятся в URL в адресной строке браузера. Это не проблема, если вы используете только использование ajax на той же странице. <h:inputHidden>, кстати, не подходит, поскольку он будет конфессионально терять свое значение, когда ошибка конверсии или валидации происходит в форме.

Чтобы заставить их снова появиться в URL-адресе, вам нужно <f:viewParam> и includeViewParams. Чтобы работать includeViewParams, вам нужно объявить следующее в как исходную страницу agreement.xhtml...

<f:metadata>
    <f:viewParam name="site" value="#{agreement.site}" />
    <f:viewParam name="serviceId" value="#{agreement.serviceId}" />
</f:metadata>

... и целевая страница generated.xhtml:

<f:metadata>
    <f:viewParam name="site" value="#{generated.site}" />
    <f:viewParam name="serviceId" value="#{generated.serviceId}" />
</f:metadata>

Теперь вы можете отправить перенаправление, включая параметры представления, следующим образом:

public String generateMethod() {
    // ...

    return "generated?faces-redirect=true&includeViewParams=true";
}

Обратите внимание, что bean должен быть @ViewScoped, чтобы поддерживать эти параметры между открытием страницы с формой и отправкой формы, а также ошибками проверки. В противном случае, придерживаясь @RequestScoped bean, вы должны сохранить их как <f:param> в компонентах команды:

<h:commandButton ...>
    <f:param name="site" value="#{generated.site}" />
    <f:param name="serviceId" value="#{generated.serviceId}" />
</h:commandButton>

Нет способа установить их для <f:ajax> внутренних компонентов ввода, тогда ваш bean должен быть действительно @ViewScoped.


В качестве альтернативы, если вы уже используете служебную библиотеку JSF OmniFaces, вы также можете просто заменить <h:form> на <o:form> следующим образом (см. также пример витрины):

<o:form includeRequestParams="true">

Это в основном все. Это приведет к созданию <form action> с включенной текущей строкой запроса.

<form action="/app/agreement.xhtml?site=US&serviceId=AABBCC" ...>

Эти параметры запроса затем доступны только на карте параметров запроса формы submit. Вам не нужны дополнительные метаданные /viewparams, и вам также не нужно отправлять перенаправление, и при необходимости bean можно сохранить @RequestScoped.

public String generateMethod() {
    // ...

    return "generated";
}

Или, если вы используете библиотеку "довольно URL", такую ​​как PrettyFaces или FacesViews, или, возможно, что-то домашнее и намерено представить точно так же, как и в адресной строке браузера, тогда вы можете использовать useRequestURI вместо.

<o:form useRequestURI="true">

См. также:

Ответ 2

Ваш generateMethod должен возвращать

return "generated?site=US&amp;serviceId=AABBCC&amp;faces-redirect=true";

Вы даже можете заменить &amp; на &, но избегайте его в своем xhtml.

В вашем generated.xhtml вы можете поймать параметры, которые передаются с помощью <f:viewParam>, как этот

<f:metadata>
    <f:viewParam name="site" value="#{yourBean.site}"/><!--Make sure you have a setter-->
    <f:viewParam name="serviceId" value="#{yourBean.serviceId}"/><!--Make sure you have a setter-
</f:metadata>
<h:head>