Почему FullAjaxExceptionHandler не просто выполняет перенаправление ExternalContext #()?

В OmniFaces, FullAjaxExceptionHandler, после того, как вы нашли правильную страницу ошибок, вызывает время выполнения JSF для создания представления и рендеринга он вместо страницы, которая включает вызов AJAX.

Почему это? ИМХО было бы проще просто выполнить ExternalContext#redirect()? Существуют ли конкретные причины для этого?

Мы пишем наш собственный ExceptionHandler на основе FullAjaxExceptionHandler и хотели понять причину этого дизайна.

Ответ 1

Основная цель FullAjaxExceptionHandler заключается в том, чтобы позволить исключениям во время запросов ajax вести себя точно так же, как исключения во время запросов без аякса. Разработчик должен иметь возможность повторно использовать страницы ошибок в обоих условиях, не беспокоясь о состоянии при реализации страниц с ошибками.

Переадресация не является частью нормального потока во время запросов без аякса. Механизм по умолчанию <error-page> в web.xml выполняет перемотку вперед, чтобы отобразить страницу ошибки, а не перенаправление. Если было выполнено перенаправление, все атрибуты запроса страницы ошибки, такие как javax.servlet.error.exception, будут потеряны и отобразятся как null. Более того, обычная практика заключается в размещении страниц ошибок в /WEB-INF, чтобы предотвратить, что конечные пользователи могут напрямую обращаться (и добавлять их в закладки и совместно использовать). Перенаправление требовало бы, чтобы они были общедоступными, что указывает на серьезную проблему дизайна (намеренная целевая страница на самом деле является реальной страницей ошибок?).

Если вам действительно нужно выполнить перенаправление на/с вашей страницы ошибки, либо homegrow - специальный обработчик исключений, который явно вызывает ExternalContext#redirect() и не использует механизм web.xml <error-page>, либо добавляет <meta http-equiv="refresh" ...> в заголовок HTML страницы с ошибкой (пример здесь).

Если вы действительно намеревались перенаправить на какую-либо страницу входа в систему при возникновении ViewExpiredException, вы должны понимать, что существует большая разница между случаями "Пользователь не вошел в систему" ​​и "Сессия/просмотр истек". Для первого вы не должны вообще ловить ViewExpiredException, но используйте простой фильтр сервлета, который проверяет, вошел ли пользователь в систему и соответственно перенаправлять, задолго до вызова FacesServlet. Обычная система проверки подлинности (JAAS, Shiro, Spring Безопасность и т.д.) Также работает именно так.

См. также: