Как сервер устанавливает приоритет для типа страницы ошибок web.xml? - PullRequest
10 голосов
/ 14 марта 2011

У меня есть две страницы ошибок;1 - для SpecificExceptionA, а другой - для Throwable.

<error-page>
  <exception-type>org.SpecificExceptionA</exception-type>
  <location>/WEB-INF/views/error/timedout.jsp</location>
</error-page>

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/WEB-INF/views/error/error.jsp</location>
</error-page>

Если в моем файле web.xml определены оба эти параметра, то все идет в /error/error.jsp.

Если ятолько определенное определенное исключение идет на соответствующую страницу;но другие ошибки идут по умолчанию для tomcat (кроме 404)

Есть ли лучший способ указать конкретные обработчики исключений?Я использую весну 3.0.

Ответы [ 2 ]

11 голосов
/ 14 марта 2011

Это не относится только к Tomcat.Это специфично для Servlet API.Способ определения страницы ошибки указан в главе 9.9.2 Спецификация API сервлета 2.5 .Вот фрагмент релевантности:

SRV.9.9.2 Страницы с ошибками

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

Итак, ваш SpecificExceptionA, вероятно, был заключен в ServletException и, следовательно, java.lang.Throwable является ближайшим совпадением на 1-м проходе.Когда вы удалите эту запись, будет выполнен второй проход с исключением в виде обёртки, и, таким образом, ваш SpecificExceptionA получит совпадение.

Правильный способ определения общей страницы ошибок HTTP 500 - это отобразить ее на error-code вместо exception-type:

<error-page>
    <exception-type>org.SpecificExceptionA</exception-type>
    <location>/WEB-INF/views/error/timedout.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/views/error/error.jsp</location>
</error-page>

Если это не вариант по какой-то неясной причинеОдин из способов обойти это - создать Filter, который прослушивает url-pattern из /* и делает в основном следующее:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    try {
        chain.doFilter(request, response);
    } catch (ServletException e) {
        Throwable rootCause = e.getRootCause();
        if (rootCause instanceof SpecificExceptionA) {
            throw (SpecificExceptionA) rootCause;
        } else {
            throw e;
        }
    }
}

Он должен расширяться только от RuntimeExceptionчтобы заставить его работать.

1 голос
/ 14 марта 2011

Завелся, используя класс Springs SimpleMappingExceptionResolver

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="org.*.*.ResponseTimeExceededException">
                <!-- the name of the jsp to use for this exception -->
                error/timedout
            </prop>
        </props>
    </property>
    <property name="defaultErrorView" value="error/error"/>
</bean>
...