【问题标题】:Hide/handle servlet exception stack trace output隐藏/处理 servlet 异常堆栈跟踪输出
【发布时间】:2011-01-19 11:04:02
【问题描述】:

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

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

如何阻止异常跟踪出现在我的日志中?它将在现场自动进行监控,如果出现此类错误,则会向支持团队发出误报。

任何帮助表示赞赏。

编辑

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

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>

【问题讨论】:

    标签: java servlets stack-trace servlet-filters


    【解决方案1】:

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

    编辑

    链中的其他过滤器可能会在抛出 ServletException 之前对其进行记录。在您发布的堆栈跟踪中,似乎有一个ajax4jsf 的过滤器可能正在记录ServletException。你有这个的来源吗?您的web.xml 中有多少过滤器?

    编辑 2

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

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

    【讨论】:

    • 但不幸的是没有工作。我将过滤器条目(filterfilter-mapping)放在 RichFaces 过滤器之前,当会话超时时,我仍然在日志中获得堆栈跟踪。我以非常标准的方式使用 Log4J。
    • Jason 非常感谢您的坚持。我已经编辑了我的帖子以包含我的过滤器的完整有序列表。我看到你提到的 al4sf 过滤器,但我觉得我必须把它放在那里。另一方面,配置是另一回事-我相信这个定义是在richfaces设置文档中推荐的-请随意建议您如何根据我的OP更好地配置它。
    • 好的,我去看看。非常感谢您的意见。
    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的发言。在回答您的问题时,否 - 堆栈跟踪始终是最先出现的。
    • 那么我关于重新抛出问题的猜想一定是错误的。不幸的是,我目前没有更多的想法。
    【解决方案3】:

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

    【讨论】:

    • 过滤器是我自己写的。您的示例本质上是我已经编写的(除非我没有将我的示例限制为 http 协议)。我已经编辑了我的帖子,使其更加具体。
    • 你没有在那里处理 ViewExpiredException。
    • 不,但我将它作为一个 RunTimeException 来处理。
    • 是的,我看到了,但你再扔一次!而且它不是 RuntimeException 的 instanceof,它是 RuntimeException 的子类。
    • @Elijah:RuntimeException 子类的实例 RuntimeException 的实例。
    猜你喜欢
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 2012-09-21
    • 2011-01-05
    • 1970-01-01
    • 2012-05-17
    相关资源
    最近更新 更多