error handling程序Servlet:如何获取exception原因

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

 java.lang.Exception /ExceptionHandler  

对?

在我的(通用)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()为null。

如果servletcontainer捕获的exception是ServletException并且声明捕获除ServletException之外的exception,那么它的原因实际上将被解包并存储为"javax.servlet.error.exception" 。 所以你基本上已经把它作为throwable变量,你不需要在它上面调用getCause()

另请参见Servlet 2.5规范第9.9.2节的第5段:

如果没有包含exception-type error-page声明适合使用类层次结构匹配,并且抛出的exception是ServletException或其子类, 则容器将提取ServletException.getRootCause方法定义的包装exception 。 对错误页面声明进行第二次传递,再次尝试匹配错误页面声明,但使用包装的exception。

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

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

编辑。

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

有关深入讨论,请参阅无根本例外情况 。

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