隐藏/处理servlet异常堆栈跟踪输出

时间:2011-01-19 11:04:03

标签: java servlets stack-trace servlet-filters

this帖子开始,我想到了另一个问题,我似乎无法在互联网上找到答案。

我有一个servlet过滤器,可以检测会话超时并重定向到错误页面。由于我的初出茅庐的java,我使用了try catch块来捕获异常并优雅地处理它们,但是在会话超时的情况下,上下文是无效的,所以我不认为我有任何代码我可以做到这一点停止'viewId无法恢复'stace trace出现在我的日志中,即使我有一个过滤器处理它。

如何阻止异常跟踪显示在我的日志中?它将在现场进行自动监控,对于此类错误,这将是对支持团队的误报。

任何帮助表示感谢。

修改

为了更清楚,我的代码片段目前是

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(request, response);
    } catch (ServletException e) {
        logger.error("Caught Servlet Exception");
        Throwable rootCause = e.getRootCause();
        logger.error("Root cause is " + rootCause.toString());

        if (rootCause instanceof RuntimeException) { // This is true for any FacesException.
            logger.error("Rethrowing exception as RuntimeException" + rootCause.toString());
            throw (RuntimeException) rootCause; // Throw wrapped RuntimeException instead of ServletException.
        } else {
            throw e;
        }
    }
}

日志说:

    |STDOUT| 2011-01-19 10:40:57,803 | ERROR | [http-8080-5]: Exception in the filter chain
    javax.servlet.ServletException: viewId:/index.jsf - View /index.jsf could not be restored.
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
        at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
<snip>
        at java.lang.Thread.run(Unknown Source)
    Caused by: javax.faces.application.ViewExpiredException: viewId:/index.jsf - View /index.jsf could not be restored.
<snip>
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
        ... 21 more
    19-Jan-2011 10:40:57 org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet Faces Servlet threw exception
    javax.faces.application.ViewExpiredException: viewId:/index.jsf - View /index.jsf could not be restored.
        at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:185)
<snip>
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Unknown Source)
    |STDOUT| 2011-01-19 10:40:57,803 | ERROR | [http-8080-5]: Caught Servlet Exception
    |STDOUT| 2011-01-19 10:40:57,803 | ERROR | [http-8080-5]: Root cause is javax.faces.application.ViewExpiredException: viewId:/index.jsf - View /index.jsf could not be restored.
    |STDOUT| 2011-01-19 10:40:57,803 | ERROR | [http-8080-5]: Rethrowing exception as RuntimeExceptionjavax.faces.application.ViewExpiredException: viewId:/index.jsf - View /index.jsf could not be restored.

从代码中可以看出,我在过滤器中捕获了servlet异常,但堆栈仍然出现在日志中。

下一次编辑 我的web.xml中的完整过滤器列表如下:

<filter>
    <filter-name>Error</filter-name>
    <filter-class>prismClient.ErrorFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Error</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <display-name>RichFaces Filter</display-name>
    <filter-name>richfaces</filter-name>
    <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>richfaces</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

3 个答案:

答案 0 :(得分:4)

过滤器按照web.xml文件中定义的顺序执行。在您的情况下,看起来首先执行jfaces过滤器并在自定义过滤器有机会过滤掉之前记录堆栈跟踪。尝试在web.xml中填写第一个过滤条目。

修改

链中的某些其他过滤器可能会在ServletException抛出它之前记录它。在您发布的堆栈跟踪中,似乎有ajax4jsf的过滤器可能正在记录ServletException。你有这个来源吗?过滤器如何包含在web.xml

编辑2

看起来ajax4jsf正在捕获ServletException并在将其退回之前记录错误消息。我建议您获取正在使用的ajax4jsf版本的源代码,并查看堆栈跟踪(BaseXMLFilter.java第178行和BaseFilter.java第290行)中的行并搜索日志记录语句。如果找到它们,可以从源中删除它们并重建ajax4jsf,或者在日志记录配置文件中禁用该类别。我不建议使用后者,因为您将错过过滤器中可能出现的其他错误。

如果这不是错误消息的来源,那么恐怕我的想法已经用完了。

答案 1 :(得分:1)

可能是因为你重新抛出异常,无论记录什么,它仍然会得到它。即使您阻止了ServletException并重新抛出RunTimeException(ViewExpiredException也是如此),过滤器链中更高的东西可能会重新包装它。

您在此方法中编写的任何日志是否也会在堆栈跟踪之前显示在日志中?

答案 2 :(得分:0)

您是否尝试过自己编写会话过滤器?找一个很好的例子here