Сервлет обработчика ошибок: как получить причину исключения - PullRequest
12 голосов
/ 17 ноября 2010

В моем файле 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 ]

21 голосов
/ 17 ноября 2010

Если исключение, обнаруженное сервлетконтейнером, является ServletException, а <error-page> объявляется для того, чтобы перехватить исключение , отличное , чем ServletException, то его причина будет фактически развернута и сохранена как "javax.servlet.error.exception".Таким образом, у вас уже есть переменная throwable, и вам не нужно вызывать getCause().

См. Также 5-й абзац главы 9.9.2 Спецификация сервлета 2.5 :

Если нет объявления error-page, содержащего exception-type, подходит с использованием совпадения иерархии классов, и выбрасывается исключение ServletException или его подкласс, контейнер извлекает упакованныйисключение , как определено методом ServletException.getRootCause.Второй проход выполняется над объявлениями страницы с ошибками, снова предпринимается попытка сопоставления с объявлениями страницы с ошибками, но вместо этого используется переносимое исключение.

Кстати, лучше использовать RequestDispatcher#ERROR_EXCEPTION константа вместо жесткого кодирования.

Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
0 голосов
/ 17 ноября 2010

Редакция.

Хорошо, это может быть неправильно, у меня нет личного опыта работы с сервлетами обработки ошибок: Вместо getCause () , добавьте instanceof проверку для ServletException, если он пройдет, приведите Throwable к ServletException и используйте getRootCause () . (BalusC, похоже, имеет лучшее решение для более новых версий 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...