错误处理程序Servlet:如何获得异常原因

时间:2022-04-05 21:12:57

I have an error servlet configured in my web.xml:

我的web中配置了一个错误servlet。

<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/ExceptionHandler</location>
</error-page>

right?

对吧?

In my (generically) servlet:

在我的servlet(一般):

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        ...
        ...
    } catch (Exception e) {
        throw new ServletException("some mesage", e);
    }
}

so, "e" will be the root cause in this case.

因此,e是这个例子的根本原因。

In my ExceptionHandler class, I have:

在我的ExceptionHandler类中,我有:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
    throwable.getCause() //NULL
}

this is the problem. throwable.getCause() is null.

这就是问题所在。throwable.getCause()是null。

2 个解决方案

#1


19  

If the exception caught by the servletcontainer is a ServletException and the <error-page> is declared to catch an exception other than ServletException, then its cause will actually be unwrapped and stored as "javax.servlet.error.exception". So you basically already have it as throwable variable and you don't need to call getCause() on it.

如果servletcontainer捕获的异常是一个ServletException,并且 被声明为捕获一个除ServletException之外的异常,那么它的原因实际上将被打开并存储为“javax.servlet.error.exception”。基本上你已经有了一个可抛出的变量,你不需要调用getCause()。

See also 5th paragraph of chapter 9.9.2 of Servlet 2.5 specification:

参见Servlet 2.5规范第9.9.2章第5段:

If no error-page declaration containing an exception-type fits using the class-hierarchy match, and the exception thrown is a ServletException or subclass thereof, the container extracts the wrapped exception, as defined by the ServletException.getRootCause method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.

如果没有包含异常类型的错误页面声明,使用类层次结构匹配,而抛出的异常是一个ServletException或子类,那么容器就会提取包装的异常,这是由ServletException定义的。getRootCause方法。在错误页面声明上进行第二次传递,再次尝试与错误页面声明进行匹配,但是使用包装的异常。

By the way, it's better to use the RequestDispatcher#ERROR_EXCEPTION constant instead of hardcoding it.

顺便说一下,最好使用RequestDispatcher#ERROR_EXCEPTION常量而不是硬编码。

Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

#2


-1  

EDITED.

编辑。

Ok, this might be wrong, I do not have personal experience with error handling servlets: Instead of getCause(), add an instanceof check for ServletException, if it passes, cast your Throwable to ServletException and use getRootCause(). (BalusC seems to have a better solution, for newer Servlet API versions)

好的,这可能是错误的,我没有使用错误处理servlet的个人经验:不是getCause(),而是添加一个ServletException的instanceof check,如果它通过,将您的可丢弃对象转换为ServletException并使用getRootCause()。(对于较新的Servlet API版本,BalusC似乎有更好的解决方案)

See Exceptions Without Root Cause for in-depth discussion.

请查看无根本原因的异常以进行深入讨论。

Newer Servlet API versions do not have this issue, but if you are using some old version (2.4 or older) you should also update your ServletException throwing code:

更新的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;
    }
}

#1


19  

If the exception caught by the servletcontainer is a ServletException and the <error-page> is declared to catch an exception other than ServletException, then its cause will actually be unwrapped and stored as "javax.servlet.error.exception". So you basically already have it as throwable variable and you don't need to call getCause() on it.

如果servletcontainer捕获的异常是一个ServletException,并且 被声明为捕获一个除ServletException之外的异常,那么它的原因实际上将被打开并存储为“javax.servlet.error.exception”。基本上你已经有了一个可抛出的变量,你不需要调用getCause()。

See also 5th paragraph of chapter 9.9.2 of Servlet 2.5 specification:

参见Servlet 2.5规范第9.9.2章第5段:

If no error-page declaration containing an exception-type fits using the class-hierarchy match, and the exception thrown is a ServletException or subclass thereof, the container extracts the wrapped exception, as defined by the ServletException.getRootCause method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.

如果没有包含异常类型的错误页面声明,使用类层次结构匹配,而抛出的异常是一个ServletException或子类,那么容器就会提取包装的异常,这是由ServletException定义的。getRootCause方法。在错误页面声明上进行第二次传递,再次尝试与错误页面声明进行匹配,但是使用包装的异常。

By the way, it's better to use the RequestDispatcher#ERROR_EXCEPTION constant instead of hardcoding it.

顺便说一下,最好使用RequestDispatcher#ERROR_EXCEPTION常量而不是硬编码。

Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

#2


-1  

EDITED.

编辑。

Ok, this might be wrong, I do not have personal experience with error handling servlets: Instead of getCause(), add an instanceof check for ServletException, if it passes, cast your Throwable to ServletException and use getRootCause(). (BalusC seems to have a better solution, for newer Servlet API versions)

好的,这可能是错误的,我没有使用错误处理servlet的个人经验:不是getCause(),而是添加一个ServletException的instanceof check,如果它通过,将您的可丢弃对象转换为ServletException并使用getRootCause()。(对于较新的Servlet API版本,BalusC似乎有更好的解决方案)

See Exceptions Without Root Cause for in-depth discussion.

请查看无根本原因的异常以进行深入讨论。

Newer Servlet API versions do not have this issue, but if you are using some old version (2.4 or older) you should also update your ServletException throwing code:

更新的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;
    }
}