Сервлет обработчика ошибок: как получить причину исключения
В моем файле web.xml настроен сервлет ошибки:
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/ExceptionHandler</location>
</error-page>
право?
В моем (в общем) сервлете:
doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
...
...
} catch (Exception e) {
throw new ServletException("some mesage", e);
}
}
Таким образом, "е" будет основной причиной в этом случае.
В моем классе ExceptionHandler у меня есть:
doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
throwable.getCause() //NULL
}
это проблема. throwable.getCause() имеет значение null.
2 ответа
Если исключение, пойманное сервлетконтейнером, является ServletException
и <error-page>
объявлено, что ловит исключение, кроме ServletException
, тогда его причина будет фактически развернута и сохранена как "javax.servlet.error.exception"
, Таким образом, у вас в основном уже есть как throwable
переменная и вам не нужно звонить getCause()
в теме.
См. Также 5-й абзац главы 9.9.2 спецификации Servlet 2.5:
Если нет
error-page
декларация, содержащаяexception-type
подходит с использованием сопоставления иерархии классов, и выбрасывается исключениеServletException
или его подкласс, контейнер извлекает упакованное исключение, как определеноServletException.getRootCause
метод. Второй проход выполняется над объявлениями страниц с ошибками, снова предпринимается попытка сопоставления с объявлениями страниц с ошибками, но вместо этого используется переносимое исключение.
Кстати, лучше использовать RequestDispatcher#ERROR_EXCEPTION
константа вместо жесткого кодирования это.
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
Редакция.
Хорошо, это может быть неправильно, у меня нет личного опыта работы с сервлетами обработки ошибок: вместо getCause() добавьте instanceof
проверьте ServletException, если оно прошло, приведите Throwable к ServletException и используйте getRootCause (). (BalusC, кажется, имеет лучшее решение для более новых версий Servlet API)
Посмотрите Исключения Без Первопричины для всестороннего обсуждения.
В более новых версиях Servlet API такой проблемы нет, но если вы используете какую-то старую версию ( 2.4 или более раннюю), вам также следует обновить свой код выдачи ServletException:
doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
...
...
} catch (Exception e) {
ServletException se = new ServletException(e.getMessage(), e);
se.initCause(e);
throw se;
}
}