В чем разница между перенаправлением и навигацией / пересылкой и когда что использовать?
В чем разница между навигацией в 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()
затем.