Как перемещаться в JSF? Как сделать URL-адрес текущей страницы (а не предыдущей)

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

Я понимаю, что это связано с тем, как JSF всегда отправляет форму на одну и ту же страницу, а затем просто отображает любую страницу, которую контроллер возвращает, в браузер, который не знает, как изменилось расположение страницы.

Кажется, что JSF существует уже достаточно долго, чтобы иметь дело с чистым, надежным способом справиться с этим. Если да, не могли бы вы поделиться?

Я нашел различные обходные пути, но, к сожалению, ничего похожего на реальное твердое решение.

  • Просто признайте, что URL-адрес вводит в заблуждение.
  • Добавить "?faces-redirect=true" в возвращаемое значение каждого действия bean, а затем
    • выяснить, как заменить @RequestScoped на что-то еще (Flash Scopes, CDI-разговор, @SessionScoped,...).
    • согласитесь, что для каждого пользовательского действия есть два маршрута HTTP.
  • Используйте какой-либо метод (например, стороннюю библиотеку или собственный код), чтобы скрыть имя страницы в URL-адресе, всегда используя один и тот же общий URL-адрес для каждой страницы.

Если "?faces-redirect=true" так же хорошо, как и получается, существует ли способ настроить все приложение таким образом, чтобы обрабатывать все запросы?

Ответ 1

Действительно, JSF как объект, ориентированный на форму, использует структуру POST для того же URL-адреса, что и страница с формой <h:form>. Вы можете подтвердить это, посмотрев URL <form action> сгенерированного вывода HTML. Это в терминах веб-разработки, охарактеризованных как обратная передача. Навигация по обратной передаче по умолчанию не вызывает новый запрос к новому URL-адресу, но вместо этого загружает целевую страницу в качестве содержимого ответа. Это действительно сбивает с толку, когда вы просто хотите навигация по страницам.

Как правило, правильный подход к навигации/перенаправлению зависит от бизнес-требований и idempotence (read: "bookmarkability" ) запрос.

  • Если запрос является идемпотентным, просто используйте форму/ссылку GET вместо формы POST (т.е. используйте <form>, <h:link> или <h:button> вместо <h:form> и <h:commandXxx>).
    Например, навигация по страницам, форма поиска в Google и т.д.

  • Если запрос не является идемпотентным, просто покажите результаты условно в одном представлении (т.е. return null или void и используйте, например, <h:message(s)> и/или rendered).
    Например, ввод/редактирование данных, многошаговый мастер, модальный диалог, форма подтверждения и т.д.

  • Если запрос не является идемпотентным, но целевая страница является идемпотентной, просто отправьте перенаправление после POST (т.е. верните результат с помощью ?faces-redirect=true или <redirect/>).
    Например, показывая список всех данных после успешного редактирования, перенаправляйте после входа и т.д.

Обратите внимание, что чистая навигация по страницам обычно является идемпотентной, и именно поэтому многие стартеры JSF терпят неудачу, злоупотребляя командами/кнопками для этого, а затем после этого жалуются, что эти URL не изменяются. Также обратите внимание, что случаи навигации очень редко используются в приложениях реального мира, которые разрабатываются в отношении SEO/UX, и это приводит к тому, что многие учебники JSF терпят неудачу, позволяя читателям поверить иначе.

Также обратите внимание, что использование POST абсолютно не "более безопасно", чем GET, поскольку параметры запроса не отображаются сразу в URL-адресе. Они все еще видны в теле запроса HTTP и все еще манипулируются. Поэтому нет абсолютно никаких оснований предпочитать POST для идемпотентных запросов ради "безопасности". Реальная безопасность заключается в использовании HTTPS вместо HTTP и проверке методов бизнес-обслуживания, если в настоящее время зарегистрированный пользователь может запрашивать объект X или манипулировать объектом X и т.д. Применимая система безопасности предлагает аннотации для этого.

См. также: