В чем разница между перенаправлением и навигацией / пересылкой и когда что использовать?

В чем разница между навигацией в JSF

FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, url);

и перенаправление

HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(url);

и как решить когда использовать что?

Проблема с навигацией заключается в том, что URL страницы не изменяется, если только faces-redirect=true добавляется в строку запроса URL-адреса навигации. Тем не менее, в моем случае добавление faces-redirect=true выдает ошибку, если я хочу перенаправить на страницу, отличную от JSF, как обычную страницу HTML.

И еще один вариант, как BalusC предложил при ошибке перенаправления JSF 2.0

1 ответ

Решение

Прежде всего, термин "перенаправление" - это в мире веб-разработки действие отправки клиенту пустого HTTP-ответа только с Location заголовок с новым URL-адресом, по которому клиент должен отправить совершенно новый запрос GET. Итак, в основном:

  • Клиент отправляет HTTP-запрос somepage.xhtml,
  • Сервер отправляет ответ HTTP с Location: newpage.xhtml заголовок
  • Клиент отправляет HTTP-запрос newpage.xhtml (это отражается в адресной строке браузера!)
  • Сервер отправляет ответ HTTP обратно с содержанием newpage.xhtml,

Вы можете отследить это с помощью встроенного / дополненного инструментария разработчика веб-браузера. Нажмите F12 в Chrome/IE9/Firebug и проверьте раздел "Сеть", чтобы увидеть его.

Обработчик навигации JSF не отправляет перенаправление. Вместо этого он использует содержимое целевой страницы в качестве ответа HTTP.

  • Клиент отправляет HTTP-запрос somepage.xhtml,
  • Сервер отправляет ответ HTTP обратно с содержанием newpage.xhtml,

Однако, как исходный запрос HTTP был somepage.xhtml, URL в адресной строке браузера остается неизменным. Если вы знакомы с базовым API сервлета, вы должны понимать, что это имеет тот же эффект, что и RequestDispatcher#forward(),


Что касается того, потянувHttpServletResponseиз-под капюшонов JSF и вызоваsendRedirect()на это правильное использование; нет, это не правильное использование. Журналы вашего сервера будут загромождены IllegalStateException Это потому, что таким образом вы не говорите JSF, что вы уже взяли на себя управление обработкой ответов, и поэтому JSF не должна выполнять свою работу по умолчанию по обработке ответов. Вы должны на самом деле выполнять FacesContext#responseComplete() после этого.

Кроме того, каждый раз, когда вам нужно импортировать что-то изjavax.servlet.*Пакет в JSF-артефакте, подобный управляемому бину, должен полностью прекратить писать код и дважды подумать, действительно ли вы все делаете правильно, и спросить себя, не существует ли уже "стандартного пути JSF" для всего, что вы пытаетесь для достижения и / или если задача действительно принадлежит управляемому компоненту JSF (в некоторых случаях лучше использовать простой фильтр сервлетов).

Правильный способ выполнения перенаправления в JSF использует faces-redirect=trueСтрока запроса в результате действия:

public String submit() {
    // ...
    return "/newpage.xhtml?faces-redirect=true";
}

Или используяExternalContext#redirect()когда вы не находитесь внутри метода действия, такого как метод слушателя ajax или prerender:

public void listener() throws IOException {
    // ...
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml");
}

(да, вам не нужно ставитьtry-catchвокруг этого наIOExceptionпросто дайте исключение пройти throws, сервлетконтейнер с этим справится)

Или используя NavigationHandler#handleNavigation()в определенных случаях, если вы используете случаи навигации XML и / или пользовательский обработчик навигации с некоторым встроенным слушателем:

public void listener() {
    // ...
    FacesContext fc = FacesContext.getCurrentInstance();
    NavigationHandler nh = fc.getApplication().getNavigationHandler();
    nh.handleNavigation(fc, null, "/newpage.xhtml?faces-redirect=true");
}

Относительно того, почему обработчик навигации не работает для файлов "простого HTML", это просто потому, что обработчик навигации может обрабатывать только представления JSF, но не другие файлы. Вы должны использоватьExternalContext#redirect()затем.

Смотрите также:

Другие вопросы по тегам