【问题标题】:Error Handler Servlet: how to get exception cause错误处理程序 Servlet:如何获取异常原因
【发布时间】:2011-05-11 14:11:36
【问题描述】:

我的 web.xml 中配置了一个错误 servlet:

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

对吗?

在我的(一般)servlet 中:

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

所以,在这种情况下,“e”将是根本原因。

在我的 ExceptionHandler 类中,我有:

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

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

【问题讨论】:

  • 您确定这是同一个例外并且您没有混淆吗?顺便说一句,您的“通用 servlet”代码在异常处理代码中有拼写错误,无法编译。
  • 也许你有 new ServletException("some message" + e) 而不是 new ServletException("some message", e)?仔细检查提供的 Throwable 对象是有意义的,以查看您的代码中某处可能存在错误。 ;-)
  • 我现在写了“通用 servlet”。请忽略语法错误。
  • 我不能使用 new ServletException("some message" + e) 除非 e.toString() 给我所有的堆栈跟踪。这就是我想要的。错误的原始行。
  • 别管我的cmets,我只是添加了一个答案:-)

标签: java servlets exception-handling


【解决方案1】:

已编辑。

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

请参阅Exceptions Without Root Cause 进行深入讨论。

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

【讨论】:

  • java.lang.Exception 无法转换为 javax.servlet.ServletException。也许如果我将 web.xml 更改为异常类型?
  • @user:这确实不是ServletException。你看到我的回答了吗?
  • 是的,最好遵循 BalusC 的建议,我也更新了我的答案。
  • @Neeme:您更新的代码也毫无意义。它已经在内部设置了原因。此外,getRootCause() 只是委托给getCause()。你看到我的回答了吗?
  • 取决于 Servlet API 的版本,你看到我链接的页面了吗?它已经过时(2005 年),但您不能对 Servlet API 版本做出太多假设,所以我想我的回答对于旧版 Servlet API 用户仍然具有一定的价值。
【解决方案2】:

如果 servletcontainer 捕获的异常是 ServletException 并且声明 &lt;error-page&gt; 捕获除 ServletException 之外的异常其他,那么它的原因实际上将被解包并存储为 @ 987654326@。所以你基本上已经把它作为throwable 变量,你不需要在它上面调用getCause()。

另见Servlet 2.5 specification第9.9.2章第5段:

如果没有包含exception-type 的error-page 声明适合使用 类层次匹配,抛出的异常是 ServletException 或 作为其子类,容器提取包装的异常,如 ServletException.getRootCause 方法。对错误进行第二次传递 页面声明,再次尝试匹配错误页面声明, 而是使用包装的异常。

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

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

【讨论】:

  • 我知道。谢谢。这是一个旧系统,我很难修复。问题是堆栈跟踪的顶部是 servlet 中的“ throw new ...”行,而不是异常的真正原因。真正的原因是在块内部 try {},对吧?正确的。 :)
  • Servlet 根据合同要求将任何捕获的异常包装在 ServletException 中,以便您可以利用 servletcontainer 的工具进一步处理它。原始异常将被解包并按原样进一步处理。
  • 我猜我使用 java 5 的 servlet 实现(2.4)没有这个常量。
  • 可能你导入了错误的界面?它应该是javax.servlet.RequestDispatcher 之一(单击答案中的链接以查看 javadoc)。您可能不小心在 IDE 中自动完成了错误的操作。例如 Jersey (JAX-RS) 也有这样的接口。
  • 如果您使用的是 Servlet API 2.4,那么我建议您按照我的建议更新您的代码(请参阅我的回答),看看它是否能解决问题。
猜你喜欢
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多